package sintactico;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;

import lexico.AnalizadorLexico;
import lexico.AnalizadorLexicoEstados;
import lexico.Campodevuelto;
import lexico.Camposdevuelto;
import lexico.Declaracion;
import lexico.EstadoAceptacion;
import lexico.EstadoError;
import lexico.EstadoNoAceptacion;
import lexico.Expresion;
import lexico.Operador;
import lexico.Parametrodevuelto;
import lexico.Tipodevuelto;
import lexico.Token;
import lexico.Transicion;
import lexico.Declaracion.Tipo;
import lexico.Declaracion.ClaseTabla;
import lexico.Token.TipoToken;
import tabla_simbolos.Array;
import tabla_simbolos.Campo;
import tabla_simbolos.Parametro;
import tabla_simbolos.Puntero;
import tabla_simbolos.Referencia;
import tabla_simbolos.Registro;
import tabla_simbolos.Tabla;
import tabla_simbolos.TipoBasico;
import tabla_simbolos.Variable;
import tabla_simbolos.Parametro.Modo;


public class AnalizadorSintactico { 
	/*Constantes*/
	private static final int LONGPROLOGO = 13;
	private static final int LONGINICIO = 4;
	private static final int LONGEPILOGO = 13;
	private static final int LONGINICIOPASO = 3;
	private static final int LONGFINPASO = 1;

	/*Atributos*/
	private AnalizadorLexico al;
	private Tabla ts=new Tabla();
	private int dir;
	private int n;
	private int nmax;
	private int etq;
	private int etqProlog;

	private ArrayList<String> cod=new ArrayList <String>();
	
	/*Constructora*/
	public AnalizadorSintactico(Tabla ts, ArrayList<String> cod, int n, int nmax, int etq){
		this.ts=ts;
		this.cod=cod;
		this.n=n;
		this.nmax=nmax;
		this.etq=etq;
		
	}
	
	public AnalizadorSintactico() {
		super();
	}

/*Metodos*/
	
	public void empezar(){
		cod.add("1");
		cod.add("2");
		cod.add("3");
		cod.add("4");
	}
	
	public void emite(String string) {
		cod.add(string);
	}
	
	private void emite(String string, int i) {
		cod.set(i, string);
	}
	
	public AnalizadorLexicoEstados configuraScanner()
	{
		AnalizadorLexicoEstados ale= new AnalizadorLexicoEstados();
		String l_09= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		String l= "abcdefghijklmnopqrstuvwxyz";  
		String L= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		String lL= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
		String next=" .:,;()[]<>=-*/%+/n!\t";
		String next0=" :,;()[]<>=-+/*/n!%\t";
		String d= "123456789";
		String d0= "0123456789";
		String op= "+-*/%";
		EstadoNoAceptacion estadoInicial= new EstadoNoAceptacion("e0", new Transicion("  \n \t", "e0"), new Transicion(L,"e1"),new Transicion(l, "e1"), new Transicion(";", "e45"), new Transicion(d, "e3"), new Transicion("+", "e5"), new Transicion("-", "e7"), new Transicion("0", "e9"), new Transicion("'", "e20"), new Transicion("<", "e23"), new Transicion(">", "e27"), new Transicion("!", "e31"), new Transicion("=", "e33"), new Transicion("*", "e36"), new Transicion("/", "e37"),	new Transicion("%", "e38"),	new Transicion("(", "e40"),	new Transicion(")", "e41"), new Transicion(":", "e42"), new Transicion(".", "e43"), new Transicion("{", "e63"), new Transicion("}", "e64"), new Transicion(",", "e66"), new Transicion("[", "e65"), new Transicion("]", "e67"));
		estadoInicial.setInicial(true);
		ale.addEstado(estadoInicial);
		ale.addEstado(new EstadoNoAceptacion("e1", new Transicion(l_09, "e1"), new Transicion(next,"e2"), new Transicion(null, "e48")));
		ale.addEstado(new EstadoAceptacion("e2", TipoToken.tokens_iden, true));
		ale.addEstado(new EstadoNoAceptacion("e3", new Transicion(d0, "e3"), new Transicion(".", "e10"), new Transicion("Ee", "e14"), new Transicion(null, "e4")));
		ale.addEstado(new EstadoAceptacion("e4", TipoToken.literal_natural, true));
		ale.addEstado(new EstadoNoAceptacion("e5", new Transicion(d0, "e69"), new Transicion(null, "e6")));
		ale.addEstado(new EstadoAceptacion("e69", TipoToken.t_suma, true));
		ale.addEstado(new EstadoAceptacion("e6", TipoToken.t_suma, true));
		ale.addEstado(new EstadoNoAceptacion("e7", new Transicion(d, "e46"), new Transicion(">", "e68"), new Transicion(null, "e8")));
		ale.addEstado(new EstadoAceptacion("e8", TipoToken.t_resta, true));
		ale.addEstado(new EstadoNoAceptacion("e9", new Transicion(".", "e10"), new Transicion("Ee", "e14"),new Transicion(next0, "e4"),new Transicion(null, "e48")));
		ale.addEstado(new EstadoNoAceptacion("e10", new Transicion("0", "e11"), new Transicion(d, "e49")));
		ale.addEstado(new EstadoNoAceptacion("e11", new Transicion("0", "e12"),new Transicion(d, "e49"), new Transicion(null, "e18")));
		ale.addEstado(new EstadoNoAceptacion("e12", new Transicion("0", "e12"),new Transicion(d, "e49"), new Transicion(null, "e48")));
		ale.addEstado(new EstadoAceptacion("e13", TipoToken.literal_natural, true));		
		ale.addEstado(new EstadoNoAceptacion("e14", new Transicion("-", "e15"), new Transicion(d, "e17"), new Transicion("0", "e16")));		
		ale.addEstado(new EstadoNoAceptacion("e15", new Transicion("0", "e16"), new Transicion(d, "e17")));		
		ale.addEstado(new EstadoAceptacion("e16", TipoToken.literal_real, false));		
		ale.addEstado(new EstadoNoAceptacion("e17", new Transicion(d0, "e17"), new Transicion(null, "e18")));
		ale.addEstado(new EstadoAceptacion("e18", TipoToken.literal_real, true));			
		ale.addEstado(new EstadoNoAceptacion("e20", new Transicion(l_09, "e21")));		
		ale.addEstado(new EstadoNoAceptacion("e21", new Transicion("'", "e22")));		
		ale.addEstado(new EstadoAceptacion("e22", TipoToken.literal_caracter, false));	
		ale.addEstado(new EstadoNoAceptacion("e23", new Transicion("<", "e24"), new Transicion("=", "e25"), new Transicion(null, "e26")));		
		ale.addEstado(new EstadoAceptacion("e24", TipoToken.t_dIzq, false));		
		ale.addEstado(new EstadoAceptacion("e25", TipoToken.t_menorIgual, false));		
		ale.addEstado(new EstadoAceptacion("e26", TipoToken.t_menor, true));		
		ale.addEstado(new EstadoNoAceptacion("e27", new Transicion(">", "e28"), new Transicion("=", "e29"), new Transicion(null, "e30")));		
		ale.addEstado(new EstadoAceptacion("e28", TipoToken.t_dDer, false));		
		ale.addEstado(new EstadoAceptacion("e29", TipoToken.t_mayorIgual, false));		
		ale.addEstado(new EstadoAceptacion("e30", TipoToken.t_mayor, true));		
		ale.addEstado(new EstadoNoAceptacion("e31", new Transicion("=", "e32")));		
		ale.addEstado(new EstadoAceptacion("e32", TipoToken.t_distinto, false));		
		ale.addEstado(new EstadoNoAceptacion("e33", new Transicion("=", "e34"),new Transicion(null, "e44")));
		ale.addEstado(new EstadoAceptacion("e34", TipoToken.t_igual, false));		
		ale.addEstado(new EstadoAceptacion("e36", TipoToken.t_mult, false));
		ale.addEstado(new EstadoAceptacion("e37", TipoToken.t_div, false));
		ale.addEstado(new EstadoAceptacion("e38", TipoToken.t_mod, false));
		ale.addEstado(new EstadoNoAceptacion("e40", new Transicion("e","e51"),new Transicion("c","e55"), new Transicion("r","e57"),new Transicion("n","e60"),new Transicion(null,"e62")));
		ale.addEstado(new EstadoAceptacion("e41", TipoToken.t_cerrado, false));
		ale.addEstado(new EstadoAceptacion("e42", TipoToken.t_dospuntos, false));
		ale.addEstado(new EstadoAceptacion("e43", TipoToken.t_punto, false));
		ale.addEstado(new EstadoAceptacion("e44", TipoToken.t_asig, true));
		ale.addEstado(new EstadoAceptacion("e45", TipoToken.t_puntocoma, false));
		ale.addEstado(new EstadoAceptacion("e47", TipoToken.literal_entero,true));
		ale.addEstado(new EstadoNoAceptacion("e46", new Transicion(d0,"e46"), new Transicion(null,"e47"), new Transicion(".","e10")));
		ale.addEstado(new EstadoError("e48"));
		ale.addEstado(new EstadoNoAceptacion("e49", new Transicion("0", "e12"),new Transicion(d, "e49"),new Transicion("Ee", "e14"), new Transicion(null, "e18")));
		ale.addEstado(new EstadoNoAceptacion("e51", new Transicion("n","e52"), new Transicion(null, "e62")));
		ale.addEstado(new EstadoNoAceptacion("e52", new Transicion("t","e53"), new Transicion(null, "e62")));
		ale.addEstado(new EstadoNoAceptacion("e53", new Transicion(")","e54"), new Transicion(null, "e62")));
		ale.addEstado(new EstadoAceptacion("e54", TipoToken.t_cast, false));		
		ale.addEstado(new EstadoNoAceptacion("e55", new Transicion("a","e56"), new Transicion(null, "e62")));
		ale.addEstado(new EstadoNoAceptacion("e56", new Transicion("r","e53"), new Transicion(null, "e62")));
		ale.addEstado(new EstadoNoAceptacion("e57", new Transicion("e","e58"), new Transicion(null, "e62")));
		ale.addEstado(new EstadoNoAceptacion("e58", new Transicion("a","e59"), new Transicion(null, "e62")));
		ale.addEstado(new EstadoNoAceptacion("e59", new Transicion("l","e53"), new Transicion(null, "e62")));
		ale.addEstado(new EstadoNoAceptacion("e60", new Transicion("a","e61"), new Transicion(null, "e62")));
		ale.addEstado(new EstadoNoAceptacion("e61", new Transicion("t","e53"), new Transicion(null, "e62")));
		ale.addEstado(new EstadoAceptacion("e62", TipoToken.t_abierto, true));
		ale.addEstado(new EstadoAceptacion("e63", TipoToken.t_inibloque, false));
		ale.addEstado(new EstadoAceptacion("e64", TipoToken.t_finbloque, false));	
		ale.addEstado(new EstadoAceptacion("e65", TipoToken.t_corcheteabierto, false));
		ale.addEstado(new EstadoAceptacion("e67", TipoToken.t_corchetecerrado, false));
		ale.addEstado(new EstadoAceptacion("e66", TipoToken.t_coma, false));	
		ale.addEstado(new EstadoAceptacion("e68", TipoToken.t_flecha, false));
				
		return ale;
	}
	
	public void calcula(String cadena){
		//abro y leo el fichero que me pasan	
		int columna=0;		//caracter que estamos leyendo de la linea
		String input="";	//todo el programa
		try {					
			Scanner sc = new Scanner(new File(cadena));			
			while(sc.hasNext()) {
		    	String linea = sc.nextLine();
		   		if (!linea.isEmpty()){
		   			while(columna<linea.length()){  		
		   				char c= linea.charAt(columna);
		   				if(c=='@') columna=linea.length();	//si es un comentario paso de linea
		    			else{	
		    				input=input+c;
		    				if (columna==linea.length()-1)input=input+' ';
		    					columna++;
		    			} 	
		    		}//fin while
		    		columna=0;
		    		input=input+'\n';
		    	}//fin if empty 		
		    }//fin while hasNext	
		}//fin try
		catch (FileNotFoundException e1) {e1.printStackTrace(); }				
		al=this.configuraScanner();
		try{
			al.inicializa(input);
			Programa();
			al.reconoceToken(TipoToken.t_salto);
			System.out.println("");	
		} catch (Exception e) {System.out.println(e.getMessage());}
	}
	
	public void Programa() throws Exception
	{
		Prog();  
		al.reconoceToken(TipoToken.t_eof);
		return;
	}
	
	public void Prog() throws Exception			
	{
		al.reconoceToken(TipoToken.t_programa);
		al.reconoceToken(TipoToken.t_dospuntos);
		al.reconoceToken(TipoToken.tokens_iden);
		al.reconoceToken(TipoToken.t_punto);
		//ts creada por defecto
		dir=0;
		n=0;
		nmax=0;
		etq=etq+LONGINICIO;
		empezar();
		emite("ir-a ?");
		int etqaux=etq;
		etq=etq+1;
		ArrayList<String> pend=Decs();
		inicio(nmax,dir);
		if(!pend.isEmpty()) throw new Exception ("Error tipos pendientes de declarar"); 
		parchea(etqaux,etq);
		Ins();
		emite("stop");
		return;
	}

	public ArrayList<String> Decs() throws Exception
	{
		if(al.consultaTipo(TipoToken.t_declaracion)){
			al.reconoceToken(TipoToken.t_declaracion);
			al.reconoceToken(TipoToken.t_dospuntos);
			return Ds();
		}else{return null;}
	}
	
	public ArrayList<String> Ds()throws Exception
	{
		ArrayList<String> pendh=new ArrayList<String>();
		Declaracion dec=D();
 		if( !dec.getTipotabla().equals(ClaseTabla.procedimiento) && ts.existeID(dec.getLexema()) && ts.consultaNivel(dec.getLexema(),n)==n) 
			throw new Exception ("Variable o tipo ya declarada o declarado");
		
		//añadimos una variable a la tabla de simbolos
		if (dec.getTipotabla().equals(ClaseTabla.var)){
			
			//la variable puede ser una referencia
			if (dec.getTipo().equals(Tipo.ref)) {
				Variable v= new Variable(dec.getTipo(),dec.getPropsRef());
				v.setTam(dec.getPropsRef().getTam());
				ts.anadirIDVar(dec.getLexema(), dir, n, dec.getTipotabla(), v);
				dir=dir+dec.getPropsRef().getTam();   
			}
			//la variable puede ser un array. El array puede ser un array de referencias, literales, arrays, registros o punteros
			else if (dec.getTipo().equals(Tipo.array)) {
				Array arr=null;
				if (dec.getPropsArray().getPropsRef()!=null)
					arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsRef(),dec.getPropsArray().getTam());
				else if (dec.getPropsArray().getPropsVar()!=null)
					arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsVar(),dec.getPropsArray().getTam());
				else if (dec.getPropsArray().getPropsArray()!=null)
					arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsArray(),dec.getPropsArray().getTam());
				else if (dec.getPropsArray().getPropsReg()!=null)
					arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsReg(),dec.getPropsArray().getTam());
				else if (dec.getPropsArray().getPropsPunt()!=null)
					arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsPunt(),dec.getPropsArray().getTam());
				else if (dec.getPropsArray().getPropsTBas()!=null)
					arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsTBas(),dec.getPropsArray().getTam());
				
				Variable v= new Variable(dec.getTipo(),arr);
				v.setTam(arr.getTam());
				
				ts.anadirIDVar(dec.getLexema(), dir, n, dec.getTipotabla(), v);
				dir=dir+dec.getPropsArray().getTam();   //cuidado q aqui no se si es necceario pero creo q si
				
			}
			//la variable puede ser un registro. Los campos de un registro puede ser un referencias, literales, arrays, registros o punteros
			else if (dec.getTipo().equals(Tipo.registro)) {
				Registro reg=null;
				Campo c=null;
				ArrayList<Campo> campos= new ArrayList<Campo>();
				for (int i=0;i<dec.getPropsReg().getNum_campos();i++){
					if (dec.getPropsReg().getCampos().get(i).getPropsRef()!=null){
						c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsRef());
						c.setTam(1);
					}
					if (dec.getPropsReg().getCampos().get(i).getPropsVar()!=null){
						c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsVar());
						c.setTam(dec.getPropsReg().getCampos().get(i).getPropsVar().getTam());
					}
					if (dec.getPropsReg().getCampos().get(i).getPropsArray()!=null){
						c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsArray());
						c.setTam(dec.getPropsReg().getCampos().get(i).getPropsArray().getTam());
					}	
					if (dec.getPropsReg().getCampos().get(i).getPropsReg()!=null){
						c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsReg());
						c.setTam(dec.getPropsReg().getCampos().get(i).getPropsReg().getTam());
					}	
					if (dec.getPropsReg().getCampos().get(i).getPropsPunt()!=null){
						c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsPunt());
						c.setTam(dec.getPropsReg().getCampos().get(i).getPropsPunt().getTam());
					}
					if (dec.getPropsReg().getCampos().get(i).getPropsTBas()!=null){
						c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsTBas());
						c.setTam(dec.getPropsReg().getCampos().get(i).getPropsTBas().getTam());
					}
					campos.add(c);
				}
				int tam_reg=0;
				for (int i=0;i<campos.size();i++) tam_reg= tam_reg + campos.get(i).getTam();
				//reg=new Registro(dec.getTipo(),campos,tam_reg);
				reg=new Registro(dec.getTipo(),campos,tam_reg, campos.size());
				Variable v=new Variable(dec.getTipo(),reg);
				v.setTam(tam_reg);
				ts.anadirIDVar(dec.getLexema(), dir, n, dec.getTipotabla(), v);
				dir=dir+dec.getPropsReg().getTam(); //lo mismo
				
			}
			//la variable puede ser un puntero. El puntero puede ser un puntero a una referencia, a un literal, a un registro, a un array o a un puntero
			else if (dec.getTipo().equals(Tipo.puntero)) {
				Puntero p=null;
				if (dec.getPropsPunt().getPropsRef()!=null)
					p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsRef(), dec.getPropsPunt().getTam());
				else if (dec.getPropsPunt().getPropsVar()!=null)
					p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsVar(), dec.getPropsPunt().getTam());
				else if (dec.getPropsPunt().getPropsArray()!=null)
					p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsArray(), dec.getPropsPunt().getTam());
				else if (dec.getPropsPunt().getPropsReg()!=null)
					p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsReg(), dec.getPropsPunt().getTam());
				else if (dec.getPropsPunt().getPropsPunt()!=null)
					p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsPunt(), dec.getPropsPunt().getTam());
				else if (dec.getPropsPunt().getPropsTBas()!=null)
					p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsTBas(), dec.getPropsPunt().getTam());
				
				Variable v= new Variable(dec.getTipo(),p);
				v.setTam(p.getTam());
				ts.anadirIDVar(dec.getLexema(), dir, n, dec.getTipotabla(), v);
				dir=dir+dec.getPropsPunt().getTam(); 
				
			}
			//la variable puede ser un literal (tipo basico)
			else { 
				dec.getPropsVar().setTam(1); 
				ts.anadirIDVar(dec.getLexema(),dir,n,dec.getTipotabla(),dec.getPropsVar());
				dir=dir+dec.getPropsVar().getTam();
			}
		}
		
		//añadimos un tipo a la tabla de simbolos
		else if (dec.getTipotabla().equals(ClaseTabla.tipo)){
			
			//un tipo puede ser un array. El array puede ser un array de referencias, literales, arrays, registros o punteros
			if (dec.getTipo().equals(Tipo.array)){
				Array arr=null;
				if (dec.getPropsArray().getPropsRef()!=null){
					arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsRef(),dec.getPropsArray().getTam());
					arr.setTam(arr.getNelems());
				}else if (dec.getPropsArray().getPropsVar()!=null){
					arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsVar(),dec.getPropsArray().getTam());
					arr.setTam(arr.getTam());
				}else if (dec.getPropsArray().getPropsArray()!=null){
					arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsArray(),dec.getPropsArray().getTam());
					arr.setTam(arr.getPropsArray().getTam());
				}else if (dec.getPropsArray().getPropsReg()!=null){
					arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsReg(),dec.getPropsArray().getTam());
					arr.setTam(arr.getPropsReg().getTam());
				}else if (dec.getPropsArray().getPropsPunt()!=null){
					arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsPunt(),dec.getPropsArray().getTam());
					arr.setTam(arr.getPropsPunt().getTam());
				}
				else if (dec.getPropsArray().getPropsTBas()!=null){
					arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsTBas(),dec.getPropsArray().getTam());
					arr.setTam(arr.getPropsPunt().getTam());
				}
				ts.anadirIDArray(dec.getLexema(),0,n,dec.getTipotabla(),arr);
			}
			//el tipo puede ser un registro. Los campos de un registro puede ser un referencias, literales, arrays, registros o punteros
			if (dec.getTipo().equals(Tipo.registro)) {
				Registro reg=null;
				Campo c=null;
				ArrayList<Campo> campos= new ArrayList<Campo>();
				for (int i=0;i<dec.getPropsReg().getNum_campos();i++){
					if (dec.getPropsReg().getCampos().get(i).getPropsRef()!=null){
						c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsRef());
						c.setTam(1);
					}
					if (dec.getPropsReg().getCampos().get(i).getPropsVar()!=null){
						c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsVar());
						c.setTam(dec.getPropsReg().getCampos().get(i).getPropsVar().getTam());
					}
					if (dec.getPropsReg().getCampos().get(i).getPropsArray()!=null){
						c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsArray());
						c.setTam(dec.getPropsReg().getCampos().get(i).getPropsArray().getTam());
					}
					if (dec.getPropsReg().getCampos().get(i).getPropsReg()!=null){
						c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsReg());
						c.setTam(dec.getPropsReg().getCampos().get(i).getPropsReg().getTam());
					}
					if (dec.getPropsReg().getCampos().get(i).getPropsPunt()!=null){
						c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsPunt());
						c.setTam(dec.getPropsReg().getCampos().get(i).getPropsPunt().getTam());
					}
					if (dec.getPropsReg().getCampos().get(i).getPropsTBas()!=null){
						c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsTBas());
						c.setTam(dec.getPropsReg().getCampos().get(i).getPropsTBas().getTam());
					}
					campos.add(c);
				}
				int tam_reg=0;
				for (int i=0;i<campos.size();i++) tam_reg= tam_reg + campos.get(i).getTam();
				//reg=new Registro(dec.getTipo(),campos,tam_reg);
				reg=new Registro(dec.getTipo(),campos,tam_reg, campos.size());  
				ts.anadirIDRegistro(dec.getLexema(),0,n,dec.getTipotabla(),reg);
			}
			//el tipo puede ser un puntero. El puntero puede ser un puntero a una referencia, a un literal, a un registro, a un array o a un puntero
			if (dec.getTipo().equals(Tipo.puntero)) {
				Puntero p=null;
				if (dec.getPropsPunt().getPropsRef()!=null)
					p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsRef(), dec.getPropsPunt().getTam());
				else if (dec.getPropsPunt().getPropsVar()!=null)
					p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsVar(), dec.getPropsPunt().getTam());
				else if (dec.getPropsPunt().getPropsArray()!=null)
					p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsArray(), dec.getPropsPunt().getTam());
				else if (dec.getPropsPunt().getPropsReg()!=null)
					p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsReg(), dec.getPropsPunt().getTam());
				else if (dec.getPropsPunt().getPropsPunt()!=null)
					p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsPunt(), dec.getPropsPunt().getTam());
				else if (dec.getPropsPunt().getPropsTBas()!=null)
					p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsTBas(), dec.getPropsPunt().getTam());
				
				p.setTam(1);
				ts.anadirIDPuntero(dec.getLexema(),0,n,dec.getTipotabla(),p);
				//pend=dec.getLexema(); //posible error revisar aqui--> Si , pq no esta pendiente el puntero sino a lo que referencia no?
				///--- Añado todos lo pendientes de dec no???
				if(dec.getPend()!=null){
					for(int i=0;i<dec.getPend().size();i++)
						if(!ts.existeID(dec.getPend().get(i))) pendh.add(dec.getPend().get(i));
				
				}	///---
				//pendh.add(pend);
			}
			if(dec.getTipo().toString().contains("literal")){
				if(dec.getTipotabla().equals(ClaseTabla.var)){
					Variable v= new Variable(dec.getTipo(),1);
					ts.anadirIDVar(dec.getLexema(), 0, n, ClaseTabla.var, v);
				}
				else if(dec.getTipotabla().equals(ClaseTabla.tipo)){ 
					TipoBasico tb= new TipoBasico(dec.getTipo(),1);
					ts.anadirIDTipoBasico(dec.getLexema(),0,n,ClaseTabla.tipo,tb);
				}
			} 
		} else if (dec.getTipotabla().equals(ClaseTabla.procedimiento)){}
		else throw new Exception("Error lexico: token encontrado no valido."+ " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());    
		return RDs(pendh);   
	}
		
	public ArrayList<String> RDs(ArrayList<String> pendh) throws Exception
	{
		Declaracion dec;
		if (al.consultaTipo(TipoToken.t_puntocoma)){
			al.reconoceToken(TipoToken.t_puntocoma);
			dec = D();									
			//if(!dec.getTipotabla().equals(ClaseTabla.procedimiento) && ((ts.existeID(dec.getLexema()))&& ts.consultaNivel(dec.getLexema())==n)) throw new Exception ("Error Sintactico contextual: variable o tipo duplicada o duplicado"+ " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna()); 
			//añadimos una variable a la tabla de simbolos
			if (dec.getTipotabla().equals(ClaseTabla.var)){
				
				//la variable puede ser una referencia
				if (dec.getTipo().equals(Tipo.ref)) {
					Variable v= new Variable(dec.getTipo(),dec.getPropsRef());
					v.setTam(ts.consultaTamano(dec.getPropsRef().getID()));
					ts.anadirIDVar(dec.getLexema(), dir, n, dec.getTipotabla(), v);
					dir=dir+dec.getPropsRef().getTam();
				}
				//la variable puede ser un array. El array puede ser un array de referencias, literales, arrays, registros o punteros
				else if (dec.getTipo().equals(Tipo.array)) {
					Array arr=null;
					if (dec.getPropsArray().getPropsRef()!=null)
						arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsRef(),dec.getPropsArray().getTam());
					else if (dec.getPropsArray().getPropsVar()!=null)
						arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsVar(),dec.getPropsArray().getTam());
					else if (dec.getPropsArray().getPropsArray()!=null)
						arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsArray(),dec.getPropsArray().getTam());
					else if (dec.getPropsArray().getPropsReg()!=null)
						arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsReg(),dec.getPropsArray().getTam());
					else if (dec.getPropsArray().getPropsPunt()!=null)
						arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsPunt(),dec.getPropsArray().getTam());
					else if (dec.getPropsArray().getPropsTBas()!=null)
						arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsTBas(),dec.getPropsArray().getTam());
					
					Variable v= new Variable(dec.getTipo(),arr);
					v.setTam(arr.getTam());
					ts.anadirIDVar(dec.getLexema(), dir, n, dec.getTipotabla(), v);
					dir=dir+dec.getPropsArray().getTam();  //BEA
				}
				//la variable puede ser un registro. Los campos de un registro puede ser un referencias, literales, arrays, registros o punteros
				else if (dec.getTipo().equals(Tipo.registro)) {
					Registro reg=null;
					Campo c=null;
					ArrayList<Campo> campos= new ArrayList<Campo>();
					for (int i=0;i<dec.getPropsReg().getNum_campos();i++){
						if (dec.getPropsReg().getCampos().get(i).getPropsRef()!=null){
							c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsRef());
							c.setTam(1);
						}
						if (dec.getPropsReg().getCampos().get(i).getPropsVar()!=null){
							c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsVar());
							c.setTam(dec.getPropsReg().getCampos().get(i).getPropsVar().getTam());
						}
						if (dec.getPropsReg().getCampos().get(i).getPropsArray()!=null){
							c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsArray());
							c.setTam(dec.getPropsReg().getCampos().get(i).getPropsArray().getTam());
						}
						if (dec.getPropsReg().getCampos().get(i).getPropsReg()!=null){
							c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsReg());
							c.setTam(dec.getPropsReg().getCampos().get(i).getPropsReg().getTam());
						}
						if (dec.getPropsReg().getCampos().get(i).getPropsPunt()!=null){
							c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsPunt());
							c.setTam(dec.getPropsReg().getCampos().get(i).getPropsPunt().getTam());
						}
						if (dec.getPropsReg().getCampos().get(i).getPropsTBas()!=null){
							c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsTBas());
							c.setTam(dec.getPropsReg().getCampos().get(i).getPropsTBas().getTam());
						}
						campos.add(c);
					}
					int tam_reg=0;
					for (int i=0;i<campos.size();i++) tam_reg= tam_reg + campos.get(i).getTam();
					reg=new Registro(dec.getTipo(),campos,tam_reg, dec.getPropsReg().getNum_campos());
					Variable v=new Variable(dec.getTipo(),reg);
					v.setTam(tam_reg);
					ts.anadirIDVar(dec.getLexema(), dir, n, dec.getTipotabla(), v);
					dir=dir+dec.getPropsReg().getTam();  //BEA
				}
				//la variable puede ser un puntero. El puntero puede ser un puntero a una referencia, a un literal, a un registro, a un array o a un puntero
				else if (dec.getTipo().equals(Tipo.puntero)) {
					Puntero p=null;
					if (dec.getPropsPunt().getPropsRef()!=null)
						p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsRef(), dec.getPropsPunt().getTam());
					else if (dec.getPropsPunt().getPropsVar()!=null)
						p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsVar(), dec.getPropsPunt().getTam());
					else if (dec.getPropsPunt().getPropsArray()!=null)
						p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsArray(), dec.getPropsPunt().getTam());
					else if (dec.getPropsPunt().getPropsReg()!=null)
						p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsReg(), dec.getPropsPunt().getTam());
					else if (dec.getPropsPunt().getPropsPunt()!=null)
						p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsPunt(), dec.getPropsPunt().getTam());
					else if (dec.getPropsPunt().getPropsTBas()!=null)
						p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsTBas(), dec.getPropsPunt().getTam());
					
					Variable v= new Variable(dec.getTipo(),p);
					v.setTam(p.getTam());
					ts.anadirIDVar(dec.getLexema(), dir, n, dec.getTipotabla(), v);
					dir=dir+dec.getPropsPunt().getTam();  //BEA
				}
			
				//la variable puede ser un literal (tipo basico)
				else {
					dec.getPropsVar().setTam(1);
					ts.anadirIDVar(dec.getLexema(),dir,n,dec.getTipotabla(),dec.getPropsVar());
					dir=dir+dec.getPropsVar().getTam();
				}
			}
			
			//añadimos un tipo a la tabla de simbolos
			else if (dec.getTipotabla().equals(ClaseTabla.tipo)){
				
				//un tipo puede ser un array. El array puede ser un array de referencias, literales, arrays, registros o punteros
				if (dec.getTipo().equals(Tipo.array)){
					Array arr=null;
					if (dec.getPropsArray().getPropsRef()!=null){
						arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsRef(),dec.getPropsArray().getTam());
					//	arr.setTam(arr.getNelems());  //yo creo q no es necesario sobre todo porque esta a null esto
						Referencia r= new Referencia(arr.getPropsRef().getT(),arr.getPropsRef().getID(),arr.getNelems()*arr.getPropsRef().getTam());
						//r.setTam(ts.damePropsTBas(dec.getPropsArray().getPropsRef().getID(),n).getTam());
						arr.setPropsRef(r);
					}
					else if (dec.getPropsArray().getPropsVar()!=null){
						arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsVar(),dec.getPropsArray().getTam());
						arr.setTam(arr.getNelems());
					}
					else if (dec.getPropsArray().getPropsArray()!=null){
						arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsArray(),dec.getPropsArray().getTam());
						arr.setTam(arr.getPropsArray().getTam());
					}
					else if (dec.getPropsArray().getPropsReg()!=null){
						arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsReg(),dec.getPropsArray().getTam());
						arr.setTam(arr.getPropsReg().getTam());
					}
					else if (dec.getPropsArray().getPropsPunt()!=null){
						arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsPunt(),dec.getPropsArray().getTam());
						arr.setTam(arr.getPropsPunt().getTam());
					}
					else if (dec.getPropsArray().getPropsTBas()!=null){
						arr= new Array(dec.getTipo(),dec.getPropsArray().getNelems(),dec.getPropsArray().getPropsTBas(),dec.getPropsArray().getTam());
						arr.setTam(arr.getPropsTBas().getTam());
					}
					
					ts.anadirIDArray(dec.getLexema(),0,n,dec.getTipotabla(),arr);
					if(pendh.contains(dec.getLexema())) {
						pendh.remove(dec.getLexema());
					}
				}
				//el tipo puede ser un registro. Los campos de un registro puede ser un referencias, literales, arrays, registros o punteros
				if (dec.getTipo().equals(Tipo.registro)) {
					Registro reg=null;
					Campo c=null;
					ArrayList<Campo> campos= new ArrayList<Campo>();
					for (int i=0;i<dec.getPropsReg().getNum_campos();i++){
						if (dec.getPropsReg().getCampos().get(i).getPropsRef()!=null){
							c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsRef());
							c.setTam(ts.consultaTamano(c.getPropsRef().getID()));
						}
						if (dec.getPropsReg().getCampos().get(i).getPropsVar()!=null){
							c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsVar());
							c.setTam(dec.getPropsReg().getCampos().get(i).getPropsVar().getTam());
						}
						if (dec.getPropsReg().getCampos().get(i).getPropsArray()!=null){
							c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsArray());
							c.setTam(dec.getPropsReg().getCampos().get(i).getPropsArray().getTam());
						}
						if (dec.getPropsReg().getCampos().get(i).getPropsReg()!=null){
							c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsReg());
							c.setTam(dec.getPropsReg().getCampos().get(i).getPropsReg().getTam());
						}
						if (dec.getPropsReg().getCampos().get(i).getPropsPunt()!=null){
							c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsPunt());
							c.setTam(dec.getPropsReg().getCampos().get(i).getPropsPunt().getTam());
						}
						if (dec.getPropsReg().getCampos().get(i).getPropsTBas()!=null){
							c=new Campo(dec.getPropsReg().getCampos().get(i).getId(), dec.getPropsReg().getCampos().get(i).getDesp(), dec.getPropsReg().getCampos().get(i).getPropsTBas());
							c.setTam(dec.getPropsReg().getCampos().get(i).getPropsTBas().getTam());
						}
						campos.add(c);
					}
					int tam_reg=0;
					for (int i=0;i<campos.size();i++) tam_reg= tam_reg + campos.get(i).getTam();
					reg=new Registro(dec.getTipo(),campos,tam_reg, dec.getPropsReg().getNum_campos());
					reg.setNum_campos(campos.size());
					ts.anadirIDRegistro(dec.getLexema(),0,n,dec.getTipotabla(),reg);
					String pendiente= dec.getLexema();
					for (int i=0;i<pendh.size();i++) {
						if (pendh.get(i).equals(pendiente)) pendh.remove(pendh.get(i));
					}
				}
				//el tipo puede ser un puntero. El puntero puede ser un puntero a una referencia, a un literal, a un registro, a un array o a un puntero
				if (dec.getTipo().equals(Tipo.puntero)) {
					Puntero p=null;
					if (dec.getPropsPunt().getPropsRef()!=null)
						p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsRef(), dec.getPropsPunt().getTam());
					else if (dec.getPropsPunt().getPropsVar()!=null)
						p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsVar(), dec.getPropsPunt().getTam());
					else if (dec.getPropsPunt().getPropsArray()!=null)
						p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsArray(), dec.getPropsPunt().getTam());
					else if (dec.getPropsPunt().getPropsReg()!=null)
						p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsReg(), dec.getPropsPunt().getTam());
					else if (dec.getPropsPunt().getPropsPunt()!=null)
						p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsPunt(), dec.getPropsPunt().getTam());
					else if (dec.getPropsPunt().getPropsTBas()!=null)
						p= new Puntero(dec.getTipo(),dec.getPropsPunt().getPropsTBas(), dec.getPropsPunt().getTam());
					
					p.setTam(1);
					ts.anadirIDPuntero(dec.getLexema(),0,n,dec.getTipotabla(),p);
					for(int i=0;i<dec.getPend().size();i++)
						if(!ts.existeID(dec.getPend().get(i))) pendh.add(dec.getPend().get(i));
					
				}
				if(dec.getTipo().toString().contains("literal")){
					if(dec.getTipotabla().equals(ClaseTabla.var)){
						Variable v= new Variable(dec.getTipo(),1);
						ts.anadirIDVar(dec.getLexema(), 0, n, ClaseTabla.var, v);
					}
					else if(dec.getTipotabla().equals(ClaseTabla.tipo)){ 
						TipoBasico tb= new TipoBasico(dec.getTipo(),1);
						ts.anadirIDTipoBasico(dec.getLexema(),0,n,ClaseTabla.tipo,tb);
					}
				}
			}	
			
			return RDs(pendh);
		}else{//RDs->landa
			return pendh;
		}
	}
	
	public Declaracion D() throws Exception 
	{
		Declaracion d = null;
		if(al.consultaTipo(TipoToken.t_tipo)){
			d=DTipo();
			d.setTipotabla(ClaseTabla.tipo);
			
		}else if(al.consultaTipo(TipoToken.t_variable))	{
			d=DVariable();
			d.setTipotabla(ClaseTabla.var);
		}else if(al.consultaTipo(TipoToken.t_procedimiento)){
			d=DProcedimiento();
			d.setTipotabla(ClaseTabla.procedimiento);
		}else throw new Exception("Error lexico: token encontrado no valido."+ " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());
		return d;
	}
	
	
	public Declaracion DTipo() throws Exception{
		al.reconoceToken(TipoToken.t_tipo);
		Token t=al.reconoceToken(TipoToken.tokens_iden);
		al.reconoceToken(TipoToken.t_asig);
		Tipodevuelto tipo = N_tipo();
		tipo.setID(t.getLexema());
		Declaracion d= new Declaracion(t.getLexema(), tipo.getTipo(),tipo.getPend(),tipo.getPropsVar(),tipo.getPropsArray(),tipo.getPropsPunt(),tipo.getPropsRef(),tipo.getPropsReg(),tipo.getPropsTBas());
		if (ts.existeID(t.getLexema()) || ts.referenciaErronea(tipo.getTipo())) throw new Exception ("Error en las declaraciones");
		return d;
	}
	
	public Declaracion DVariable() throws Exception{
		al.reconoceToken(TipoToken.t_variable);
		Token t=al.reconoceToken(TipoToken.tokens_iden);
		al.reconoceToken(TipoToken.t_tipo);
		Tipodevuelto tipo=N_tipo();
		Declaracion d= new Declaracion(t.getLexema(), tipo.getTipo(),tipo.getPend(),tipo.getPropsVar(),tipo.getPropsArray(),tipo.getPropsPunt(),tipo.getPropsRef(),tipo.getPropsReg(),tipo.getPropsTBas());
		if ((ts.existeID(t.getLexema()) && ts.consultaNivel(t.getLexema(),n)==n) || ts.referenciaErronea(tipo.getTipo())) throw new Exception ("Error en las declaraciones");
		return d;				    
	}
	
	public Declaracion DProcedimiento() throws Exception{
		int diraux=dir;
		al.reconoceToken(TipoToken.t_procedimiento);
		Token t=al.reconoceToken(TipoToken.tokens_iden);
		n=n + 1;
		ArrayList<Parametro> params=Fparams();
		if(ts.existeID(t.getLexema()) && ts.consultaNivel(t.getLexema(),n)==n) 
			throw new Exception ("Error: Nombre ya utilizado");
		Declaracion d=new Declaracion(t.getLexema());
		d.getPropsProc().setParams(params);
		ts.anadirIDProcedimiento(t.getLexema(), 0, n, ClaseTabla.procedimiento,d.getPropsProc());
		int inicio=Bloque();
		nmax=max(n,nmax);
		ts.eliminavariables(n);
		n=n-1;
		ts.anadirIDProcedimiento(t.getLexema(), 0, n, ClaseTabla.procedimiento,d.getPropsProc());
		ts.damePropsProc(t.getLexema(),n).setInicio(inicio);
		dir=diraux;
		return d;
	}
	
	private ArrayList<Parametro> Fparams() throws Exception {
		if(al.consultaTipo(TipoToken.t_abierto)){
			al.reconoceToken(TipoToken.t_abierto);
			ArrayList<Parametro> p=LFParams();
			al.reconoceToken(TipoToken.t_cerrado);
			return p;
		}
		else{
			dir=0;
			return null;
		}
	}
	
	private ArrayList<Parametro> LFParams() throws Exception {
		dir=0;
		ArrayList<Parametro> paramsh=new ArrayList<Parametro>();
		Parametrodevuelto p=FParam();
		if (p!=null){//BEA
			dir=p.getTamano();
			paramsh.add(p.getparametro());
		}
		
		return RLFParams(paramsh);
	}

	private ArrayList<Parametro> RLFParams(ArrayList<Parametro> paramsh) throws Exception {
		if(al.consultaTipo(TipoToken.t_coma)){
			al.reconoceToken(TipoToken.t_coma);
			Parametrodevuelto p=FParam();
			dir=dir+p.getTamano();
			paramsh.add(p.getparametro());
			//si falla comprobar esto: errh1 = (existeID(ts, id1) ^ ts[id1].nivel = n) v existeID(ts, id1)} 
			return RLFParams(paramsh);
		}
		else{
			return paramsh;
		}
	}
	
	private Parametrodevuelto FParam() throws Exception {
		Parametrodevuelto p=null;
		Variable v= null;
		if(al.consultaTipo(TipoToken.tparamvar)){			
			al.reconoceToken(TipoToken.tparamvar);
			Token t=al.reconoceToken(TipoToken.tokens_iden);
			if (ts.existeID(t.getLexema()) && ts.consultaNivel(t.getLexema(),n)==n) throw new Exception ("Error en el paso de parámetros, parámetro duplicado"); 
			al.reconoceToken(TipoToken.t_tipo);
			Tipodevuelto tipo=N_tipo() ;
			//en funcion del tipo de mi variable me creo un parametro u otro
				
			if (tipo.getTipo().equals(Tipo.ref)){		
				
				p=new Parametrodevuelto(t.getLexema(),tipo.dameTamano(),Modo.variable,tipo.getPropsRef(),n,dir);
				//v=new Variable(p.getparametro().getPropsRef().getT(), 1);
				v=new Variable(tipo.getTipo(), tipo.getPropsRef());
			}
			if ((tipo.getTipo().equals(Tipo.literal_booleano)) || (tipo.getTipo().equals(Tipo.literal_caracter)) || (tipo.getTipo().equals(Tipo.literal_entero)) ||
					(tipo.getTipo().equals(Tipo.literal_natural)) || (tipo.getTipo().equals(Tipo.literal_numerico))||(tipo.getTipo().equals(Tipo.literal_real))){
				p=new Parametrodevuelto(t.getLexema(),tipo.dameTamano(),Modo.variable,tipo.getPropsVar(),n,dir);
				p.setTamano(tipo.getPropsVar().getTam());
				v=new Variable(p.getparametro().getPropsVar().getT(), p.getTamano());
				
				
			}
			if (tipo.getTipo().equals(Tipo.array)){
				p=new Parametrodevuelto(t.getLexema(),tipo.dameTamano(),Modo.variable,tipo.getPropsArray(),n,dir);
				p.setTamano(tipo.getPropsArray().getTam());
				//v=new Variable(p.getparametro().getPropsArray().getT(), p.getTamano());
				v=new Variable(tipo.getTipo(),tipo.getPropsArray());
			}
			if (tipo.getTipo().equals(Tipo.registro)){
				p=new Parametrodevuelto(t.getLexema(),tipo.dameTamano(),Modo.variable,tipo.getPropsReg(),n,dir);
				p.setTamano(tipo.getPropsReg().getTam());
				//v=new Variable(p.getparametro().getPropsReg().getT(), p.getTamano());
				v=new Variable(tipo.getTipo(),tipo.getPropsReg());
			}
			if (tipo.getTipo().equals(Tipo.puntero)){
				p=new Parametrodevuelto(t.getLexema(),tipo.dameTamano(),Modo.variable,tipo.getPropsPunt(),n,dir);
				p.setTamano(tipo.getPropsPunt().getTam());
				//v=new Variable(p.getparametro().getPropsPunt().getT(), 1);
				v=new Variable(tipo.getTipo(),tipo.getPropsPunt());
			}
			if (tipo.getTipo().equals(Tipo.basico)){
				p=new Parametrodevuelto(t.getLexema(),tipo.dameTamano(),Modo.variable,tipo.getPropsTBas(),n,dir);
				p.setTamano(tipo.getPropsPunt().getTam());
				//v=new Variable(p.getparametro().getPropsTBas().getT(), 1);
				v=new Variable(tipo.getTipo(),tipo.getPropsTBas());
			}
			ts.anadirIDVar(p.getID(),dir,n,ClaseTabla.pvar,v);
			return p;
		}
		else if(al.consultaTipo(TipoToken.tparam)){
			al.reconoceToken(TipoToken.tparam);
			Token t=al.reconoceToken(TipoToken.tokens_iden);
			al.reconoceToken(TipoToken.t_tipo);
			Tipodevuelto tipo=N_tipo(); 
			//en funcion del tipo de mi variable me creo un parametro u otro
			if (tipo.getTipo().equals(Tipo.ref)){
				p=new Parametrodevuelto(t.getLexema(),tipo.dameTamano(),Modo.valor,tipo.getPropsRef(),n,dir);
				//v=new Variable(p.getparametro().getPropsRef().getT(), 1);
				v=new Variable(tipo.getTipo(), tipo.getPropsRef());
			}
			if ((tipo.getTipo().equals(Tipo.literal_booleano)) || (tipo.getTipo().equals(Tipo.literal_caracter)) || (tipo.getTipo().equals(Tipo.literal_entero)) ||
					(tipo.getTipo().equals(Tipo.literal_natural)) || (tipo.getTipo().equals(Tipo.literal_numerico))||(tipo.getTipo().equals(Tipo.literal_real))){
				p=new Parametrodevuelto(t.getLexema(),tipo.dameTamano(),Modo.valor,tipo.getPropsVar(),n,dir);
				p.setTamano(tipo.getPropsVar().getTam());
				v=new Variable(p.getparametro().getPropsVar().getT(), p.getTamano());//esta si que es asi yo creo pq es variable
			}
			if (tipo.getTipo().equals(Tipo.array)){
				p=new Parametrodevuelto(t.getLexema(),tipo.dameTamano(),Modo.valor,tipo.getPropsArray(),n,dir);
				p.setTamano(tipo.getPropsArray().getTam());
				//v=new Variable(p.getparametro().getPropsArray().getT(), p.getTamano());
				v=new Variable(tipo.getTipo(),tipo.getPropsArray());
			}
			if (tipo.getTipo().equals(Tipo.registro)){
				p=new Parametrodevuelto(t.getLexema(),tipo.dameTamano(),Modo.valor,tipo.getPropsReg(),n,dir);
				p.setTamano(tipo.getPropsReg().getTam());
				//v=new Variable(p.getparametro().getPropsReg().getT(), p.getTamano());
				v=new Variable(tipo.getTipo(),tipo.getPropsReg());
			}
			if (tipo.getTipo().equals(Tipo.puntero)){
				p=new Parametrodevuelto(t.getLexema(),tipo.dameTamano(),Modo.valor,tipo.getPropsPunt(),n,dir);
				//v=new Variable(p.getparametro().getPropsPunt().getT(), 1);
				v=new Variable(tipo.getTipo(),tipo.getPropsPunt());
			}
			if (tipo.getTipo().equals(Tipo.basico)){
				p=new Parametrodevuelto(t.getLexema(),tipo.dameTamano(),Modo.valor,tipo.getPropsTBas(),n,dir);
				//v=new Variable(p.getparametro().getPropsTBas().getT(), 1);
				v=new Variable(tipo.getTipo(),tipo.getPropsTBas());
			}
			ts.anadirIDVar(p.getID(),dir,n,ClaseTabla.var,v);
			return p;
		}
		else if (al.consultaTipo(TipoToken.t_cerrado))return null;  //BEA
		else throw new Exception("Error");
	}

	public Tipodevuelto N_tipo() throws Exception{
		if(al.consultaTipo(TipoToken.t_boolean)){
			al.reconoceToken(TipoToken.t_boolean);
			Tipodevuelto tipo=new Tipodevuelto(Tipo.literal_booleano,"",0,1,null,null,null,null,null,null,null);
			tipo.setPend(null);
			return tipo;
		}else if(al.consultaTipo(TipoToken.t_natural)){
			al.reconoceToken(TipoToken.t_natural);
			Tipodevuelto tipo=new Tipodevuelto(Tipo.literal_natural,"",0,1,null,null,null,null,null,null,null);
			tipo.setPend(null);
			
			return tipo;
		}
		else if(al.consultaTipo(TipoToken.t_entero)){
			al.reconoceToken(TipoToken.t_entero);
			Tipodevuelto tipo=new Tipodevuelto(Tipo.literal_entero,"",0,1,null,null,null,null,null,null,null);
			tipo.setPend(null);
			return tipo;
		}
		else if(al.consultaTipo(TipoToken.t_real)){
			al.reconoceToken(TipoToken.t_real);
			Tipodevuelto tipo=new Tipodevuelto(Tipo.literal_real,"",0,1,null,null,null,null,null,null,null);
			tipo.setPend(null);
			return tipo;
		}
		else if(al.consultaTipo(TipoToken.t_caracter)){
			al.reconoceToken(TipoToken.t_caracter);
			Tipodevuelto tipo=new Tipodevuelto(Tipo.literal_caracter,"",0,1,null,null,null,null,null,null,null);
			tipo.setPend(null);
			return tipo;
		}
		else if (al.consultaTipo(TipoToken.t_array)) {
			al.reconoceToken(TipoToken.t_array);
			al.reconoceToken(TipoToken.t_corcheteabierto);
			Token tok= al.reconoceToken(TipoToken.literal_natural);
			al.reconoceToken(TipoToken.t_corchetecerrado);
			al.reconoceToken(TipoToken.t_de);
			Tipodevuelto tipo=N_tipo();
			Tipodevuelto tipodev= new Tipodevuelto(Tipo.array,"",Integer.parseInt(tok.getLexema()),Integer.parseInt(tok.getLexema())*tipo.dameTamano(),tipo.getPropsArray(),tipo.getPropsPunt(),tipo.getPropsReg(),tipo.getPropsRef(),tipo.getPropsProc(),tipo.getPropsTBas(),tipo.getPropsVar());
			if (ts.referenciaErronea(tipo.getTipo())) throw new Exception ("Error ref. erronea array");
			return tipodev;
		}
		else if(al.consultaTipo(TipoToken.t_reg)){	
			al.reconoceToken(TipoToken.t_reg);
			al.reconoceToken(TipoToken.t_inibloque);
			Camposdevuelto campos=Campos();
			al.reconoceToken(TipoToken.t_finbloque);
			int ncampos=0;
			for (int i=0;i<campos.getCampos().size();i++) ncampos= ncampos+ 1;
			Registro reg=new Registro(Tipo.registro,campos.getCampos(),campos.getTam(), ncampos);
			Tipodevuelto tipo= new Tipodevuelto(Tipo.registro,"",0,0,null,null,reg,null,null,null,null);
			return tipo;
		}
		else if(al.consultaTipo(TipoToken.t_puntero)){
			al.reconoceToken(TipoToken.t_puntero);
			Tipodevuelto tipo=N_tipo();
			Tipodevuelto tipodev= new Tipodevuelto(Tipo.puntero,"",0,1,tipo.getPropsArray(),tipo.getPropsPunt(),tipo.getPropsReg(),tipo.getPropsRef(),tipo.getPropsProc(),tipo.getPropsTBas(),tipo.getPropsVar());
			tipodev.setPend(tipo.getPend());
			return tipodev;
		}
		else if(al.consultaTipo(TipoToken.tokens_iden)){		
			Token t=al.reconoceToken(TipoToken.tokens_iden);
			
			Tipodevuelto tipo;
			
			if (ts.existeID(t.getLexema())) { 
				tipo=new Tipodevuelto(Tipo.ref,t.getLexema(),0,0,ts.damePropsArray(t.getLexema(),n),ts.damePropsPuntero(t.getLexema(),n),ts.damePropsReg(t.getLexema(),n),ts.damePropsRef(t.getLexema(),n),ts.damePropsProc(t.getLexema(),n),ts.damePropsTBas(t.getLexema(),n),ts.damePropsVar(t.getLexema(),n));
			}
			else{
				Referencia referen= new Referencia(Tipo.ref,t.getLexema(),1);
				tipo=new Tipodevuelto(Tipo.ref,t.getLexema(),0,0,null,null,null,referen,null,null,null);
				tipo.anadirPend(t.getLexema());
			}
			if (ts.existeID(t.getLexema()) && !ts.consultaTipoTabla(t.getLexema()).equals(ClaseTabla.tipo)) throw new Exception ("No es un tipo");
			return tipo;
			
		}
		return null;
	}
	
	private Camposdevuelto Campos() throws Exception
	{
		Camposdevuelto c=new Camposdevuelto();
		Campodevuelto campo=Campo(0);
		c.anadeCampo(campo.getCampo());
		int desp=campo.getTam();
		c.setTam(c.getTam()+campo.getTam());
		if(campo.getPend()!=null) c.anadePend(campo.getPend());
		return RCampos(desp,c);
	}

	private Camposdevuelto RCampos(int desp, Camposdevuelto campos) throws Exception {
		if(al.consultaTipo(TipoToken.t_puntocoma)){
			al.reconoceToken(TipoToken.t_puntocoma);
			Campodevuelto campo=Campo(desp);
			campo.getCampo().setDesp(desp);
			if (campos.getCampos().contains(campo.getCampo())) throw new Exception ("campos duplicados");
			campos.anadeCampo(campo.getCampo());
			desp=desp+campo.getTam();
			if(campo.getPend()!=null) campos.anadePend(campo.getPend());
			campos.setTam(campos.getTam()+campo.getTam());
			return RCampos(desp,campos);
		}else return campos;
	}

	private Campodevuelto Campo(int j) throws Exception {
		Token t=al.reconoceToken (TipoToken.tokens_iden);
		al.reconoceToken(TipoToken.t_tipo);
		Tipodevuelto tipo=N_tipo();
		tipo.setID(t.getLexema());
		if(ts.referenciaErronea(tipo.getTipo())) throw new Exception ("Error:ref erronea campo");
		
		//Los campos de un registro puede ser un referencias, literales, arrays, registros o punteros
		Campo c=null;
		if (tipo.getPropsRef()!=null){
			c=new Campo(t.getLexema(),0, tipo.getPropsRef());
			c.setTam(1);
		}
		if (tipo.getPropsVar()!=null){
			c=new Campo(t.getLexema(), 0, tipo.getPropsVar());
			c.setTam(tipo.getPropsVar().getTam());
		}
		if (tipo.getPropsArray()!=null){
			c=new Campo(t.getLexema(), 0, tipo.getPropsArray());
			c.setTam(tipo.getPropsArray().getTam());
		}
		if (tipo.getPropsReg()!=null){
			c=new Campo(t.getLexema(), 0, tipo.getPropsReg().getCampos().get(j).getPropsReg());
			c.setTam(tipo.getPropsReg().getTam());
		}
		if (tipo.getPropsPunt()!=null){
			c=new Campo(t.getLexema(),0, tipo.getPropsReg().getCampos().get(j).getPropsPunt());
			c.setTam(tipo.getPropsPunt().getTam());
		}
		if (tipo.getPropsTBas()!=null){
			c=new Campo(t.getLexema(),0, tipo.getPropsReg().getCampos().get(j).getPropsTBas());
			c.setTam(tipo.getPropsTBas().getTam());
		}
		
		Campodevuelto campo=new Campodevuelto(c,tipo.getPend(),tipo.dameTamano());
		return campo;
	}

	private int Bloque() throws Exception {
		al.reconoceToken(TipoToken.t_inibloque);
		return FBloque();
	}

	private int FBloque() throws Exception {
		int inicio = 0;
		if(al.consultaTipo(TipoToken.t_declaracion)){
			ArrayList<String> pend_aux=Decs();
			inicio =etq;
			etqProlog=inicio;
			prologo(n,dir);
			etq=etq+LONGPROLOGO;
			Ins();
			if (!pend_aux.isEmpty()) throw new Exception ("error: declaraciones pendientes no esta vacia"); 
			epilogo(n);
			etq=etq+ LONGEPILOGO;
			emite("ir-ind");
			etq=etq+1;
			al.reconoceToken(TipoToken.t_finbloque);
		}else if(al.consultaTipo(TipoToken.t_instrucciones)){
			inicio =etq;
			etqProlog=inicio;
			prologo (n, dir);
			etq = etq + LONGPROLOGO;
			Ins();
			epilogo(n);
			etq=etq+ LONGEPILOGO;
			emite("ir-ind");
			etq=etq +1;
			al.reconoceToken(TipoToken.t_finbloque);
		}
		return inicio;
	}

	public void Ins() throws Exception
	{
		al.reconoceToken(TipoToken.t_instrucciones);
		al.reconoceToken(TipoToken.t_dospuntos);
		Is();
	}

	public void Is() throws Exception 
	{
		I();
		RIs();		
	}
	
	public void RIs() throws Exception 
	{
		if (al.consultaTipo(TipoToken.t_puntocoma))	{
			al.reconoceToken(TipoToken.t_puntocoma);
			I();
			RIs();
		}
		else return;	
	}
	
	public void I() throws Exception
	{ 
		if (al.consultaTipo(TipoToken.op_lectura))
			Ilec();
		else if (al.consultaTipo(TipoToken.op_escritura)) 
			Iesc();	
		else if (al.consultaTipo(TipoToken.tokens_iden) || al.consultaTipo(TipoToken.t_acceso_array)) 
		{ 	Token t= al.getToken();
			if (ts.consultaTipoTabla(t.getLexema()).equals(ClaseTabla.procedimiento))
				Icall(t);
			else Iasig(t);
		}
		else if (al.consultaTipo(TipoToken.t_inibloque)) 
			Ibloque();
		else if (al.consultaTipo(TipoToken.t_opsi1)) 
			Isi();
		else if (al.consultaTipo(TipoToken.op_mientras)) 
			Imientras();
		else if (al.consultaTipo(TipoToken.op_desde)) 
			Ifor();
		else if (al.consultaTipo(TipoToken.t_new)) 
			Inew();
		else if (al.consultaTipo(TipoToken.t_delete)) 
			Idel();
		else throw new Exception("Error lexico: token encontrado no valido."+ " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());    
	}

	public void Iasig(Token t) throws Exception
	{
		Expresion expaux;
		
		Tipodevuelto tipo= Mem(t);
		al.reconoceToken(TipoToken.t_asig);// en la memoria esto no esta!!
		
		expaux = Exp0(false); //cuidado con los parametros
		if (!compatibles(tipo,expaux)) throw new Exception ("Error Sintactico contextual: los tipos no coinciden"+ " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());
		//if (t.getTipo().equals("t_acceso_array") && expaux.gettipo().equals("t_acceso_array")) emite("mueve "+tipo.dameTamano(),etq-1);
		if (compatibles (expaux.gettipo(), Tipo.literal_numerico) ||compatibles (expaux.gettipo(), Tipo.literal_caracter) || compatibles (expaux.gettipo(), Tipo.literal_booleano) || expaux.getId().equals("nulo"))
			emite("desapila-ind ");
		else emite("mueve "+tipo.dameTamano());//,etq-1
		etq=etq+1;
		
	}

	public void Ilec() throws Exception
	{
		al.reconoceToken(TipoToken.op_lectura);
		al.reconoceToken(TipoToken.t_abierto);
		Token auxiden= al.reconoceToken(TipoToken.tokens_iden);
		Tipodevuelto tipo=Mem(auxiden);
		al.reconoceToken(TipoToken.t_cerrado);
		if (tipo.getTipo().equals(Tipo.literal_booleano))				
		{
			emite("lee_booleano");
			etq=etq+1;
			//emite("desapilar-dir " +ts.consultaDir(auxiden.getLexema(),n));
			emite("desapila-ind");
		}
		else{
		if (tipo.getTipo().equals(Tipo.literal_entero))			
		{
			emite("lee_entero");
			etq=etq+1;
			//emite("desapila-dir " + ts.consultaDir(auxiden.getLexema(),n));
			emite("desapila-ind");
		}
		else {
		if (tipo.getTipo().equals(Tipo.literal_natural))		
		{
			emite("lee_natural");
			etq=etq+1;
			//emite("desapila-dir " +ts.consultaDir(auxiden.getLexema(),n));
			emite("desapila-ind");
		}
		else{
		if (tipo.getTipo().equals(Tipo.literal_caracter))	
		{
			emite("lee_caracter");
			etq=etq+1;
			//emite("desapila-dir " + ts.consultaDir(auxiden.getLexema(),n));
			emite("desapila-ind");
		}
		else{
		if (tipo.getTipo().equals(Tipo.literal_real))	
		{
			emite("lee_real");
			etq=etq+1;
			//emite("desapila-dir " + ts.consultaDir(auxiden.getLexema(),n));
			emite("desapila-ind");
		}
		} 
		} 
		}
		}
		etq=etq+1;
	}
	
	public void Iesc() throws Exception
	{
		Expresion expaux;
		al.reconoceToken(TipoToken.op_escritura);
		al.reconoceToken(TipoToken.t_abierto);
		expaux=Exp0(false);
		al.reconoceToken(TipoToken.t_cerrado);
		//problema, si hay un puntero que apunte a nulo, no hemos recuperado el tipo de literal sino tipo puntero
		// voy a hacer que busque el tipo base del puntero hasta que sea literal...
		if(expaux.gettipo().equals(Tipo.puntero)){
			Puntero p;
			if(ts.damePropsPuntero(expaux.getId(),n)!=null) p= ts.damePropsPuntero(expaux.getId(),n);
			else p=ts.damePropsVar(expaux.getId(),n).getPropsPunt();
			Tipodevuelto tipopunt= new Tipodevuelto(Tipo.puntero,expaux.getId(),0,p.getTam(),null,p,null,null,null,null,null);
			while(!tipopunt.getTipo().toString().contains("literal") && !tipopunt.getTipo().equals((Tipo.registro)))
				tipopunt=tipobase(tipopunt);
			
			expaux= new Expresion(tipopunt.getID(),tipopunt.getTipo(),null);
			emite("apila-ind");
			etq=etq+1;
		}
		
		if(expaux.gettipo().equals(Tipo.literal_natural) || expaux.gettipo().equals(Tipo.registro)){
			emite("escribe_natural");
		}
		if(expaux.gettipo().equals(Tipo.literal_booleano)){
			emite("escribe_booleano");
		}
		if(expaux.gettipo().equals(Tipo.literal_entero)){
			emite("escribe_entero");
		}
		if(expaux.gettipo().equals(Tipo.literal_real)){
			emite("escribe_real");
		}
		if(expaux.gettipo().equals(Tipo.literal_caracter)){
			emite("escribe_caracter");
		}
		
			
		
		etq=etq+1;
	}

	private void Ibloque() throws Exception {
		al.reconoceToken(TipoToken.t_inibloque);
		Is();
		al.reconoceToken(TipoToken.t_finbloque);
	}
	
	private void Isi() throws Exception {
		al.reconoceToken(TipoToken.t_opsi1);
		ArrayList<Integer> etiquetas;
		etiquetas=Casos();	
		Psi_no();
		Iterator<Integer> myiterator = etiquetas.iterator();
		while(myiterator.hasNext()){
			int aux=myiterator.next();
			parchea(aux,etq);
		}
	}
	
	private void Psi_no() throws Exception {
		if(al.consultaTipo(TipoToken.t_opsi4)){
			al.reconoceToken(TipoToken.t_opsi4);
		}
		else if (al.consultaTipo(TipoToken.t_opsi3)){
			al.reconoceToken(TipoToken.t_opsi3);
			I();
			al.reconoceToken(TipoToken.t_opsi4);
		}
		else throw new Exception ("Error léxico: token no esperado");
	}

	private ArrayList<Integer> Casos() throws Exception {
		ArrayList<Integer> etiquetas=new ArrayList<Integer>();
		Caso();
		emite("ir-a ?");
		etiquetas.add(etq);
		etq=etq+1;
		RCasos(etiquetas);
		return etiquetas;
	}

	private ArrayList<Integer> RCasos(ArrayList<Integer> etiquetas) throws Exception {
		if (al.consultaTipo(TipoToken.t_opsi5)){
			al.reconoceToken(TipoToken.t_opsi5);
			Caso();
			emite("ir-a ?");
			etiquetas.add(etq);
			etq=etq+1;
			return RCasos(etiquetas);
		}else return etiquetas;
	}

	private void Caso() throws Exception {
		Expresion exp=Exp0(false);
		if (!exp.gettipo().equals(Tipo.literal_booleano)) throw new Exception ("Error:Expresión no booleana");	
		emite ("ir-f ?");
		int etqaux=etq;
		etq=etq+1; 
		al.reconoceToken(TipoToken.t_opsi2);
		I();
		parchea(etqaux,etq+1);		
	}
	
	private void Imientras() throws Exception {
		al.reconoceToken(TipoToken.op_mientras);
		int etqaux1=etq;
		Expresion exp=Exp0(false); 
		al.reconoceToken(TipoToken.op_hacer);
		emite ("ir-f ?");
		int etqaux2=etq;
		etq= etq+1;
		I();
		if (!exp.gettipo().equals(Tipo.literal_booleano)) throw new Exception ("Error: Expresión no booleana en el mientras");
		emite( "ir-a "+(etqaux1+1));
		etq=etq+1;
		parchea (etqaux2,etq);
	}
	
	private void Ifor() throws Exception {
		al.reconoceToken(TipoToken.op_desde) ;
		Token t=al.reconoceToken(TipoToken.tokens_iden);
		Tipodevuelto tipo= Mem(t);
		al.reconoceToken(TipoToken.t_asig);
		Expresion exp1=Exp0(false); 
		emite("desapila-ind"); 
		etq=etq+1;
		al.reconoceToken(TipoToken.op_hasta);
		Expresion exp2=Exp0(false);
		al.reconoceToken(TipoToken.op_hacer);
		emite("copia");
		int tmpetq=etq;
		etq=etq+1;
		accesoVar(t.getLexema());
		etq=etq+longAccesoVar(t.getLexema());	
		emite ("apila-ind");
		etq=etq+1;
		emite("compara_mayorigual");
		etq=etq+1;
		emite("ir-f ?" );
		int tmpetq2=etq;
		etq=etq+1;
		I();
		if ((!esNatural(exp1.gettipo()) && !esEntero(exp1.gettipo())) || (!esNatural(exp2.gettipo()) && !esEntero(exp2.gettipo())) 
				|| !compatibles(tipo.getTipo(),exp1.gettipo()) || !compatibles(tipo.getTipo(),exp2.gettipo()))
			throw new Exception ("Error: la expresione a evaluar debe ser entera y compatible con la variable");
		accesoVar(t.getLexema());
		etq=etq+longAccesoVar(t.getLexema());
		accesoVar(t.getLexema());
		etq=etq+longAccesoVar(t.getLexema());
		emite("apila-ind");
		etq=etq+1;
		emite("apila 1");
		etq=etq+1;
		emite("suma");
		etq=etq+1;
		emite("desapila-ind ");
		etq=etq+1;
		emite("ir-a "+(tmpetq+1));
		etq=etq+1;
		parchea(tmpetq2,etq);
		emite("desapila");
		etq=etq+1;
	}	

	private void Inew() throws Exception {		
		al.reconoceToken(TipoToken.t_new);
		Tipodevuelto tipo=Mem();
		if (!tipo.getTipo().equals(Tipo.puntero)) throw new Exception ("Error: No se puede reservar memoria para una variable que no es un puntero");
		//tipo.setPropsPunt(ts.damePropsPuntero(tipo.getID()));
		Tipodevuelto aux=referencia(tipo);//este yo creo que nunca va a hacer nada...
		//necesito el tamaño de las props ref(en este caso) del puntero:
		int tam=0;
	//	if(aux.getPropsPunt().getPropsPunt()!=null){
			while(aux.getTipo().equals(Tipo.puntero))
				aux=tipobase(aux);
		//}
		if(aux.getPropsArray()!=null) tam=aux.getPropsArray().getTam();
		
		if(aux.getPropsRef()!=null) tam=ts.consultaTamano(aux.getPropsRef().getID());
		if(aux.getPropsReg()!=null) tam=aux.getPropsReg().getTam();
		if(aux.getPropsTBas()!=null) tam=aux.getPropsTBas().getTam();
		if(aux.getPropsVar()!=null) tam=aux.getPropsVar().getTam();
		
		
		emite("reserva "+ tam);
		emite("desapila-ind");
		etq=etq+2;
	}

	private void Idel() throws Exception {
		al.reconoceToken(TipoToken.t_delete);
		Tipodevuelto tipo=Mem();
		if (!tipo.getTipo().equals(Tipo.puntero)) throw new Exception ("Error: No se puede liberar una variable que no es un puntero");
		emite("apila-ind");
		Tipodevuelto aux=referencia(tipo);
		int tam=0;
		while(aux.getTipo().equals(Tipo.puntero))
			aux=tipobase(aux);
		if(aux.getPropsArray()!=null) tam=aux.getPropsArray().getTam();
		
		if(aux.getPropsRef()!=null) tam=ts.consultaTamano(aux.getPropsRef().getID());
		if(aux.getPropsReg()!=null) tam=aux.getPropsReg().getTam();
		if(aux.getPropsTBas()!=null) tam=aux.getPropsTBas().getTam();
		if(aux.getPropsVar()!=null) tam=aux.getPropsVar().getTam();
		
		emite("libera "+ tam);	
		etq=etq+2;
	}
	
	private void Icall(Token t) throws Exception {
		al.reconoceToken(TipoToken.tokens_iden);
		ArrayList<Parametro> fparamsh = ts.damePropsProc(t.getLexema(),n).getParams();
		int etqaux=apila_ret();
		Aparams(fparamsh);
		if (ts.damePropsProc(t.getLexema(),n).getInicio()!=0) emite("ir-a " + ((ts.damePropsProc(t.getLexema(),n).getInicio())+1));
		else emite("ir-a " + (etqProlog+1));
		etq=etq+1;
		parchea(etqaux,etq);
			
		
		if (!ts.existeID(t.getLexema()) || !ts.consultaTipoTabla(t.getLexema()).equals(ClaseTabla.procedimiento)) throw new Exception ("Error: No existe un procedimiento con ese nombre");
	}

	private void Aparams(ArrayList<Parametro> fparamsh) throws Exception {
		if(al.consultaTipo(TipoToken.t_abierto)){
			al.reconoceToken(TipoToken.t_abierto);
			if (al.consultaTipo(TipoToken.t_cerrado)) 
				al.reconoceToken(TipoToken.t_cerrado);
			else {
				inicio_paso();
				etq=etq+LONGINICIOPASO;
				int nparams = LAParams(fparamsh);
				if (fparamsh.size()!=nparams) throw new Exception ("Paso de parámetros incorrecto.Nº parámetros incorrecto en la llamada");
				fin_paso();
				etq=etq+LONGFINPASO;
				al.reconoceToken(TipoToken.t_cerrado);
			}		
		}else{
			if (fparamsh.size()!=0) throw new Exception ("Paso de parámetros incorrecto. Nº parámetros incorrecto en la llamada");
			return;
		}
	}

	private int LAParams(ArrayList<Parametro> fparamsh) throws Exception {
		emite("copia") ;
		etq =etq + 1;
		Expresion exp=Exp0(true); //cuidado con el paso de parametros
		if(fparamsh.size()==0 || (exp.getmodo().equals(Modo.valor) && fparamsh.get(0).equals(Modo.variable)) 
				|| !compatibles(fparamsh.get(0), exp)) throw new Exception ("Paso de parámetros incorrecto: invocación incorrecta parámetro por variable");		
		int nparamsh = 1;
		pasoParametro(exp.getmodo(), fparamsh.get(0));
		etq=etq+ longPasoParametro(exp.getmodo(), fparamsh.get(0));
		nparamsh=RLAParams(nparamsh, fparamsh);
		return nparamsh;
	}

	private int RLAParams(int nparamsh, ArrayList<Parametro> fparamsh) throws Exception {
		if (al.consultaTipo(TipoToken.t_coma)){
			al.reconoceToken(TipoToken.t_coma);		
			emite("copia");
			direccionParFormal(fparamsh.get(nparamsh));
			etq=etq+1 + longDireccionParForma1(fparamsh.get(nparamsh));
			Expresion exp=Exp0(true);
			pasoParametro(exp.getmodo(), fparamsh.get(nparamsh));
			etq=etq + longPasoParametro(exp.getmodo(),fparamsh.get(nparamsh)); //posible error
			int nparamsh2 =nparamsh+1;
			int devolver=RLAParams(nparamsh2,fparamsh);
			if (nparamsh2 > fparamsh.size() || (fparamsh.get(nparamsh2-1).getModo().equals(Modo.variable) && exp.getmodo().equals(Modo.valor))
					|| !compatibles(fparamsh.get(nparamsh2-1), exp)) throw new Exception ("Paso de parámetros incorrecto: invocación incorrecta parámetro por variable");
			return devolver;
		}
		else return nparamsh;
	}

	public Expresion Exp0(boolean parh) throws Exception{
		Expresion expaux= Exp1(parh);  
		return FExp0(parh,expaux); //posible error: cual es el par que se le pasa
	}
	
	public Expresion FExp0(boolean parh, Expresion exph) throws Exception{
		Expresion expdevolver=null;
		Expresion expaux=null;
		if (al.esOperador()||al.consultaTipo(TipoToken.t_menor)||al.consultaTipo(TipoToken.t_mayor)||
				al.consultaTipo(TipoToken.t_mayorIgual)||al.consultaTipo(TipoToken.t_menorIgual)
				||al.consultaTipo(TipoToken.t_igual)||al.consultaTipo(TipoToken.t_distinto))
		{	
			Operador opaux;		  
			opaux=Op0(); 	
			boolean par=false;
			exph.setmodo(Modo.valor);
			expaux=Exp1(par);		
			if ((!esBooleano(exph.gettipo()) && esBooleano(expaux.gettipo())) || (esBooleano(exph.gettipo()) && !esBooleano(expaux.gettipo())) 
				|| (!esCaracter(exph.gettipo()) && esCaracter(expaux.gettipo())) || (esCaracter(exph.gettipo()) && !esCaracter(expaux.gettipo())))
				throw new Exception("Error Sintactico contextual: tipos incompatibles"+ " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());
			expdevolver=new Expresion(Tipo.literal_booleano,expaux.getmodo());
			emite(opaux.getOp());
			etq=etq+1;
			return expdevolver;
		}else return exph;
	}
	
	public Expresion Exp1(boolean parh) throws Exception
	{
		Expresion expaux=Exp2(parh);
		Expresion devolver=RExp1(parh,expaux);
		return devolver;		
	}
	
	public Expresion RExp1(boolean parh,Expresion exp) throws Exception
	{		
		Expresion expdevolver = null;
		if (al.esOperador())   
		{
			Operador op=Op1();
			if (op==null) return exp; // esto estaba de la implementacion anterior, huele a apaño y no se si hara falta
					boolean parh1=false;
					Expresion expaux1=Exp2(parh1);
					if (op.getTipo().equals(Tipo.literal_numerico))
					{
						if ((esReal(exp.gettipo())&&!esCaracter(expaux1.gettipo())) || (esReal(expaux1.gettipo())&&!esCaracter(exp.gettipo())))
							expdevolver=new Expresion(Tipo.literal_real,Modo.valor);
						else
						{
						if ((esEntero(exp.gettipo())&&!esCaracter(expaux1.gettipo())) || (esEntero(expaux1.gettipo())&&!esCaracter(exp.gettipo()))) 
							expdevolver=new Expresion(Tipo.literal_entero,Modo.valor);
		
						else 
						{
						if (esNatural(exp.gettipo()) && esNatural(expaux1.gettipo())) 
							expdevolver=new Expresion(Tipo.literal_natural,Modo.valor);
						else throw new Exception ("Error Sintactico contextual:error de tipos en "+op.getOp() + " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());
						}
						}
					}
					emite(op.getOp());
					etq=etq+1;
					expdevolver=RExp1(false,expdevolver);
					return expdevolver;
		
			
		}
		else if(al.consultaTipo(TipoToken.t_o))
		{
			int etqaux;
			al.reconoceToken(TipoToken.t_o);
			emite("copia");
			etq=etq+1;
			emite("ir-v ?");
			etqaux=etq;
			etq=etq+1;
			emite("desapila");
			etq=etq+1;
			Expresion expaux=Exp2(false); 
			expdevolver=new Expresion(Tipo.literal_booleano,Modo.valor);
			if(!exp.gettipo().equals(Tipo.literal_booleano) || !expaux.gettipo().equals(Tipo.literal_booleano))
				throw new Exception("");
			expdevolver=RExp1(false,expdevolver);
			parchea(etqaux,etq);
			return expdevolver;
		}
		return exp;	
	}
	
	public Expresion Exp2(boolean parh) throws Exception
	{
		Expresion exp=Exp3(parh);
		Expresion devolver=RExp2(parh,exp);
		return devolver;
	}
	
	public Expresion RExp2(boolean parh, Expresion exph) throws Exception
	{
		Expresion expdevolver = null;
		if (al.esOperador()){	//al esOperador hay que quitarle los booleanos!! mirad a ver
			Operador op=Op2();
			if (op==null)return exph; //igual que antes, huele a apaño del primer cuatri
					Expresion expaux =Exp3(parh);
					if (esNatural(op.getTipo()) || esReal(op.getTipo()) || esEntero(op.getTipo()) || esNumerico(op.getTipo()))
					{				
						if(op.getOp().equals("multiplica"))  
						{
							if ((esReal(exph.gettipo())&&!esCaracter(expaux.gettipo())) || (esReal(expaux.gettipo()))&&!esCaracter(exph.gettipo())) 
								expdevolver=new Expresion(Tipo.literal_real,Modo.valor);
							else 
							{
							if ((esEntero(exph.gettipo())&&!esCaracter(expaux.gettipo())) || (esEntero(expaux.gettipo()))&&!esCaracter(exph.gettipo())) 
								expdevolver=new Expresion(Tipo.literal_entero,Modo.valor);
							else
							{
							if (esNatural(exph.gettipo()) && esNatural(expaux.gettipo())) 
								expdevolver=new Expresion(Tipo.literal_natural,Modo.valor);
							else throw new Exception ("Error Sintactico contextual: Error de tipos"+ " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());
							}
						}
					}
					else 
					{
						if(op.getOp().equals("divide"))
						{
							if ((esReal(exph.gettipo())&&!esCaracter(expaux.gettipo())) || (esReal(expaux.gettipo()))&&!esCaracter(exph.gettipo())) 
								expdevolver=new Expresion(Tipo.literal_real,Modo.valor);
							else 
							{
							if ((esEntero(exph.gettipo())&&!esCaracter(expaux.gettipo())) || (esEntero(expaux.gettipo()))&&!esCaracter(exph.gettipo()))
								expdevolver=new Expresion(Tipo.literal_entero,Modo.valor);
							else
							{
							if (esNatural(exph.gettipo()) && esNatural(expaux.gettipo())) 
								expdevolver=new Expresion(Tipo.literal_natural,Modo.valor);
							else throw new Exception ("Error Sintactico contextual: Error de tipos"+ " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());
							}
							}
						}else
						{			
							if(op.getOp().equals("modulo"))
							{
								if (esEntero(exph.gettipo()) && esNatural(expaux.gettipo())) 
									expdevolver=new Expresion(Tipo.literal_entero,Modo.valor);
								else 
								{
								if (esNatural(exph.gettipo()) && esNatural(expaux.gettipo())) 
									expdevolver=new Expresion(Tipo.literal_natural,Modo.valor);
								else throw new Exception ("Error Sintactico contextual: Error de tipos"+ " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());
								}
							}
						}
					}
				}
				emite(op.getOp());
				etq=etq+1;
				RExp2(parh, expdevolver);
		
		}else if(al.consultaTipo(TipoToken.t_y)){
			al.reconoceToken(TipoToken.t_y);
			emite("copia");
			etq=etq+1;
			emite("ir-f ?");
			int etqaux=etq;
			etq=etq+1;
			emite("desapila");
			etq=etq + 1;
			Expresion expaux =Exp3(false);
			if (!expaux.gettipo().equals(Tipo.literal_booleano) || !exph.gettipo().equals(Tipo.literal_booleano))
				throw new Exception ("Tipos incorrectos");
			Expresion expaux2=new Expresion(Tipo.literal_booleano,Modo.valor);
			expdevolver=RExp2(false,expaux2);
			parchea(etqaux,etq);
			/*if (expaux.gettipo().equals(Tipo.literal_booleano) && exph.gettipo().equals(Tipo.literal_booleano))
			{
					Expresion expaux2=new Expresion(Tipo.literal_booleano,Modo.valor);
					expdevolver=RExp2(false,expaux2);
					parchea(etqaux,etq);
			}
			else throw new Exception ("Tipos incorrectos");*/
		}else return exph;
		return expdevolver;	
	}	

	public Expresion Exp3(boolean parh) throws Exception{
		Expresion expaux, expdevolver;
		expaux=Exp4(parh);
		expdevolver=FExp3(expaux);
		return expdevolver;
	}
	
	public Expresion FExp3(Expresion expaux) throws Exception{
		Expresion expdevolver=null;
		if (al.consultaTipo(TipoToken.t_dIzq) || al.consultaTipo(TipoToken.t_dDer)){
			Operador op=Op3();
			boolean parh=false;
			Expresion exp1=Exp4(parh);
			emite(op.getOp());
			etq=etq+1;
			if (exp1.gettipo().equals(Tipo.literal_natural) && expaux.gettipo().equals(Tipo.literal_natural)) 
					expdevolver=new Expresion(Tipo.literal_natural, Modo.valor);
			else throw new Exception("Error Sintactico contextual:Error de tipos"+ " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());		
			return expdevolver;
		}else return expaux;	
	}
	
	public Expresion Exp4(boolean parh) throws Exception
	{
		if (al.consultaTipo(TipoToken.t_no) ||al.consultaTipo(TipoToken.t_menos)) return Exp4a(parh);
		else return Exp4na(parh);
	}
	
	public Expresion Exp4a(boolean parh) throws Exception
	{
		Expresion exp;
		if (al.consultaTipo(TipoToken.t_no) || al.consultaTipo(TipoToken.t_menos)){
			Operador op=Op4a();
			boolean parh1=false;
			Expresion expaux=Exp4(parh1);
			if (op.getTipo().equals(Tipo.literal_booleano) && expaux.gettipo().equals(Tipo.literal_booleano)) 
				exp=new Expresion(Tipo.literal_booleano,Modo.valor);
			else 
			{
			if ((op.getTipo().equals(Tipo.literal_natural))||op.getTipo().equals(Tipo.literal_entero)||op.getTipo().equals(Tipo.literal_real) && expaux.gettipo().equals(Tipo.literal_real)) //en estos espero haber copiado bien todos los tipos y los parentesis pero no confio en ello
				exp=new Expresion(Tipo.literal_real,Modo.valor);
			else 
			{
			if ((op.getTipo().equals(Tipo.literal_natural)||op.getTipo().equals(Tipo.literal_entero)||op.getTipo().equals(Tipo.literal_real)) && expaux.gettipo().equals(Tipo.literal_natural)|| expaux.gettipo().equals(Tipo.literal_entero))
				exp=new Expresion(Tipo.literal_natural,Modo.valor);
			else throw new Exception ("Error Sintactico contextual: Error de tipos"+ ". Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());
			}
			}
			emite(op.getOp());
			etq=etq+1;
		}
		else
		{
			exp=Exp5(parh);	
		}
		return exp;
	}
	
	public Expresion Exp4na(boolean parh) throws Exception
	{
		Expresion exp;
		if (al.consultaTipo(TipoToken.t_cast)){
			Operador op=Op4na();
			boolean parh1=false;
			Exp5(parh1);
			if(op.getTipo().equals(Tipo.literal_real)) exp=new Expresion(Tipo.literal_real,Modo.valor);
			else if(op.getTipo().equals(Tipo.literal_entero)) exp=new Expresion(Tipo.literal_entero,Modo.valor);
			else if(op.getTipo().equals(Tipo.literal_natural)) exp=new Expresion(Tipo.literal_natural,Modo.valor);
			else if(op.getTipo().equals(Tipo.literal_caracter)) exp=new Expresion(Tipo.literal_caracter,Modo.valor);
			else throw new Exception("Error Sintactico contextual: Error de tipos"+ " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());           
			emite(op.getOp());
			etq=etq+1;
		}
		else exp=Exp5(parh);
		return exp;
	}
	
	public Expresion Exp5(boolean parh) throws Exception 
	{
		Expresion exp = null;
		if (al.consultaTipo(TipoToken.tokens_iden))
		{
			Token t=al.reconoceToken(TipoToken.tokens_iden);
			Tipodevuelto tipo=Mem(t);
			if(!al.consultaTipo(TipoToken.t_coma) && !al.consultaTipo(TipoToken.t_cerrado)) parh=false;
			exp=new Expresion(tipo.getID(),tipo.getTipo(),Modo.variable);
			Expresion numerico =new Expresion(Tipo.literal_numerico,null);
			Expresion boleano =new Expresion(Tipo.literal_booleano,null);
			Expresion caracter =new Expresion(Tipo.literal_caracter,null);
			if((compatibles(tipo,numerico) || compatibles(tipo,boleano) || compatibles(tipo,caracter)) && !parh)
			{	emite("apila-ind");
				etq=etq+1;
			}
		}else
		{			
		if (al.consultaTipo(TipoToken.literal_natural))
		{
			Token t=al.reconoceToken(TipoToken.literal_natural);
			exp=new Expresion(Tipo.literal_natural,Modo.valor);
			emite("apila " + t.getLexema());
			etq=etq+1;
		}
		else
		{
		if (al.consultaTipo(TipoToken.literal_entero))
		{
			Token t=al.reconoceToken(TipoToken.literal_entero);
			exp=new Expresion(Tipo.literal_entero,Modo.valor);
			emite("apila " + t.getLexema());
			etq=etq+1;
		}
		else
		{
		if(al.consultaTipo(TipoToken.literal_real))
		{
			Token t=al.reconoceToken(TipoToken.literal_real);
			exp=new Expresion(Tipo.literal_real,Modo.valor);
			emite("apila " + t.getLexema());
			etq=etq+1;
		}
		else
		{
		if(al.consultaTipo(TipoToken.literal_caracter))
		{
			Token t=al.reconoceToken(TipoToken.literal_caracter);
			exp=new Expresion(Tipo.literal_caracter,Modo.valor);
			emite("apila " + t.getLexema());
			etq=etq+1;
		}
		else
		{
		if (al.consultaTipo(TipoToken.literal_booleano))
		{
			Token t=al.reconoceToken(TipoToken.literal_booleano);
			exp=new Expresion(Tipo.literal_booleano,Modo.valor);
			emite("apila " + t.getLexema());
			etq=etq+1;
		}
		else if (al.consultaTipo(TipoToken.t_abierto))
		{
			al.reconoceToken(TipoToken.t_abierto);
			exp=Exp0(parh);
			exp.setmodo(Modo.valor);
			al.reconoceToken(TipoToken.t_cerrado);
			
		}else if(al.consultaTipo(TipoToken.t_nulo)){
			Token t=al.reconoceToken(TipoToken.t_nulo);
			exp=new Expresion(Tipo.puntero,Modo.valor);
			exp.setId("nulo");
			emite("apila " +(t.getLexema()));
			etq=etq+1;
		}
		else throw new Exception ("Error sintactico: "+ al.getToken().getLexema() + " Linea: "+ al.getLinea() + " Columna: "+ (al.getColumna()-al.getToken().getLexema().length()-1));
		}
		}
		}
		}
		}
		return exp;
	}


	private Tipodevuelto Mem(Token t) throws Exception {
		if(al.consultaTipo(TipoToken.tokens_iden)) al.reconoceToken(TipoToken.tokens_iden);
		Tipodevuelto tipoh = null;
		String lex=t.getLexema();	
		if(ts.existeID(lex)){
			if (ts.consultaTipoTabla(lex).equals(ClaseTabla.var) || ts.consultaTipoTabla(lex).equals(ClaseTabla.pvar)){
				Tipodevuelto td=new Tipodevuelto(ts.consultaTipo(lex),lex,0,ts.consultaTamano(lex),ts.damePropsVar(lex,n).getPropsArray(),ts.damePropsVar(lex,n).getPropsPunt(),ts.damePropsVar(lex,n).getPropsReg(),ts.damePropsVar(lex,n).getPropsRef(),null,ts.damePropsVar(lex,n).getPropsTBas(),null); 
				tipoh=referencia(td);
			}else throw new Exception ("Error, no es una variable");
		}else throw new Exception ("Error, no esta en la TS");
		
		accesoVar(lex);
		etq=etq+longAccesoVar(lex);
		if (ts.damecomoponentetabla(lex, n).getclase().toString()=="pvar") {
			emite("apila-ind");
			etq=etq+1;
		}
		Tipodevuelto tipodevuelto=RMem (tipoh);
		return tipodevuelto;
	}
	
	

	private Tipodevuelto Mem() throws Exception {
		Token t=al.reconoceToken(TipoToken.tokens_iden);
		Tipodevuelto tipoh;
		String lex=t.getLexema();	
		if(ts.existeID(lex)){
			if (ts.consultaTipoTabla(lex).equals(ClaseTabla.var)|| ts.consultaTipoTabla(lex).equals(ClaseTabla.pvar)){
				Tipodevuelto td=new Tipodevuelto(ts.consultaTipo(lex),lex,0,ts.consultaTamano(lex),ts.damePropsArray(lex,n),ts.damePropsPuntero(lex,n),ts.damePropsReg(lex,n),ts.damePropsRef(lex,n),ts.damePropsProc(lex,n),ts.damePropsTBas(lex,n),ts.damePropsVar(lex,n)); 
				tipoh=referencia(td);
			}else throw new Exception ("Error, no es una variable");
		}else throw new Exception ("Error, no esta en la TS");
		
		accesoVar(lex);
		etq=etq+longAccesoVar(lex);
		if (ts.damecomoponentetabla(lex, n).getclase().toString()=="pvar") {
			emite("apila-ind");
			etq=etq+1;
		}
		Tipodevuelto tipodevuelto=RMem (tipoh);
		return tipodevuelto;
	}
	
	public Tipodevuelto RMem (Tipodevuelto tipoh) throws Exception
	{
		Tipodevuelto tipoh1=null;
		Tipodevuelto tipodevolver=null;
		if (al.consultaTipo(TipoToken.t_punto))
		{
			al.reconoceToken(TipoToken.t_punto);
			Token t=al.reconoceToken(TipoToken.tokens_iden);
			Registro reg=tipoh.getPropsReg();
			ArrayList<Campo> cmps = reg.getCampos();
			ArrayList<Campo> cmps2= new ArrayList<Campo>();
			int indice=0;
			if(tipoh.getTipo().equals(Tipo.registro)){				
				if (escampo(tipoh.getPropsReg().getCampos(),t.getLexema())){
					// referencia del campo!!no de tipoh!!!    ref!(tipoh.campos[iden.lex].tipo,.ts)
					for(int i=0;i<cmps.size();i++){
						if(cmps.get(i).getId().equals(t.getLexema())) {
							indice=i ;
							cmps2.add(cmps.get(i)); 	//guarreria para pasar el campo que hace la asignacion
						}
					}
					Tipodevuelto tipocampo = null;
					Campo c=reg.getCampos().get(indice);//-->esto creo que si que es necesario....COMPROBAR!
					tipocampo=tipoCampo(c);
					tipoh1=referencia(tipocampo);
					
				}else throw new Exception ("Error sintactico: fallo al intentar acceder al campo del registro" +"' no asocia" + " Linea: "+ al.getLinea() + " Columna: "+ (al.getColumna()-al.getToken().getLexema().length()-1));
			}else throw new Exception ("Error sintactico"+ al.getToken().getLexema() +"' no asocia" + " Linea: "+ al.getLinea() + " Columna: "+ (al.getColumna()-al.getToken().getLexema().length()-1));
			
			emite("apila "+(reg.getCampos().get(indice).getDesp()));
			emite("suma");
			etq=etq+2;
			tipodevolver=RMem(tipoh1);	
		}else{
			if(al.consultaTipo(TipoToken.t_corcheteabierto)){
					al.reconoceToken(TipoToken.t_corcheteabierto);
					Expresion exp=Exp0(false); //esta a false para que compile pero hay que ver lo que vale parh 
					al.reconoceToken(TipoToken.t_corchetecerrado);
					Tipodevuelto tbase;
					if(tipoh.getTipo().equals(Tipo.array) || exp.gettipo().equals(Tipo.literal_entero) || exp.gettipo().equals(Tipo.literal_natural)){//tiene que ser entero pero lo reconoce como natural
						tbase= tipobase(tipoh);	// lo he creido necesario, pq hace:   ref!(tipoh.tbase,ts)
						tipoh1=referencia(tbase);
					}
					else throw new Exception ("Error en el vector!");
					emite("apila "+tbase.dameTamano());
					emite("multiplica");
					emite("suma");
					etq=etq+ 3;
					tipodevolver=RMem (tipoh1);
					
				}
			else
				if(al.consultaTipo(TipoToken.t_flecha)){
					al.reconoceToken(TipoToken.t_flecha);
					if(tipoh.getTipo().equals(Tipo.puntero)){
						Tipodevuelto tbase=tipobase(tipoh);
						tipoh1=referencia(tbase);		// aqui tambien llama con el tipo base
						}
					else throw new Exception ("Error en el puntero!");
					emite("apila-ind");
					etq=etq+1;
					tipodevolver=RMem (tipoh1);
				}
					
		}	
		
		if (tipodevolver==null) return tipoh;
		else return tipodevolver;
		
	}
	private Tipodevuelto tipoCampo(Campo c) {
		Tipodevuelto tipocampo = null;
		if(c.getPropsArray()!=null) {tipocampo=new Tipodevuelto(c.getPropsArray().getT(),c.getId(),c.getPropsArray().getNelems(),c.getTam(),c.getPropsArray(),null,null,null,null,null,null);}
		if(c.getPropsPunt()!=null) {tipocampo=new Tipodevuelto(c.getPropsPunt().getT(),c.getId(),0,c.getTam(),null,c.getPropsPunt(),null,null,null,null,null);}
		if(c.getPropsRef()!=null) {tipocampo=new Tipodevuelto(c.getPropsRef().getT(),c.getPropsRef().getID(),0,c.getPropsRef().getTam(),null,null,null,c.getPropsRef(),null,null,null);}
		if(c.getPropsReg()!=null) {tipocampo=new Tipodevuelto(c.getPropsReg().getT(),c.getId(),0,c.getTam(),null,null,c.getPropsReg(),null,null,null,null);}
		if(c.getPropsVar()!=null) {tipocampo=new Tipodevuelto(c.getPropsVar().getT(),c.getId(),0,c.getTam(),null,null,null,null,null,null,c.getPropsVar());}
		if(c.getPropsTBas()!=null) {tipocampo=new Tipodevuelto(c.getPropsTBas().getT(),c.getId(),0,c.getTam(),null,null,null,null,null,c.getPropsTBas(),null);}
		
		return tipocampo;
	}

	public Tipodevuelto tipobase(Tipodevuelto tipoh) throws Exception{
		Tipodevuelto tipodev=null;
		if (tipoh.getPropsArray()!=null) {//para que me sirva para sacer el tipo base de todos.
			Array a=tipoh.getPropsArray();//ahora que se que voy a buscar el tipo base de un array, lo busco segun las props
			if(a.getPropsArray()!=null)	tipodev= new Tipodevuelto(Tipo.array,tipoh.getID(),a.getPropsArray().getNelems(),tipoh.getPropsArray().getTam(),a.getPropsArray(),null,null,null,null,null,null);
			if(a.getPropsPunt()!=null)	tipodev= new Tipodevuelto(Tipo.puntero,tipoh.getID(),0,tipoh.getPropsPunt().getTam(),null,a.getPropsPunt(),null,null,null,null,null);
			if(a.getPropsReg()!=null)	tipodev= new Tipodevuelto(Tipo.registro,tipoh.getID(),0,a.getPropsReg().getTam(),null,null,a.getPropsReg(),null,null,null,null);
			if(a.getPropsRef()!=null){
				tipodev= new Tipodevuelto(Tipo.ref,tipoh.getID(),0,a.getPropsRef().getTam(),null,null,null,a.getPropsRef(),null,null,null);
				tipodev=referencia(tipodev);// no estoy muy segura,  comrpobar
			}
			if(a.getPropsVar()!=null)	tipodev= new Tipodevuelto(a.getPropsVar().getT(),tipoh.getID(),a.getNelems(),a.getTam(),null,null,null,null,null,null,a.getPropsVar());
			if(a.getPropsTBas()!=null)	tipodev= new Tipodevuelto(Tipo.basico,tipoh.getID(),0,1,null,null,null,null,null,a.getPropsTBas(),null);
			
						
		}
		if (tipoh.getPropsPunt()!=null)  {
			Puntero p=tipoh.getPropsPunt();
			if(p.getPropsArray()!=null)	tipodev= new Tipodevuelto(Tipo.array,tipoh.getID(),p.getPropsArray().getNelems(),p.getTam(),p.getPropsArray(),null,null,null,null,null,null);
			if(p.getPropsPunt()!=null)	tipodev= new Tipodevuelto(Tipo.puntero,tipoh.getID(),0,p.getTam(),null,p.getPropsPunt(),null,null,null,null,null);
			if(p.getPropsReg()!=null)	tipodev= new Tipodevuelto(Tipo.registro,tipoh.getID(),0,p.getTam(),null,null,p.getPropsReg(),null,null,null,null);
			if(p.getPropsRef()!=null){
				tipodev= new Tipodevuelto(Tipo.ref,p.getPropsRef().getID(),0,p.getPropsRef().getTam(),null,null,null,p.getPropsRef(),null,null,null);
				tipodev=referencia(tipodev);
			}
			if(p.getPropsVar()!=null)	tipodev= new Tipodevuelto(p.getPropsVar().getT(),tipoh.getID(),0,p.getTam(),null,null,null,null,null,null,p.getPropsVar());
			if(p.getPropsTBas()!=null)	tipodev= new Tipodevuelto(Tipo.basico,tipoh.getID(),0,p.getTam(),null,null,null,null,null,p.getPropsTBas(),null);
		}
		//Tipo basico de REF??? yo creo que no pq eso se consulta con ref!...
		if(tipoh.getPropsRef()!=null){
			tipodev=referencia(tipoh);
		}
		
		if (tipoh.getPropsTBas()!=null)  {
			tipodev= new Tipodevuelto(Tipo.basico,tipoh.getID(),0,tipoh.getPropsTBas().getTam(),null,null,null,null,null,tipoh.getPropsTBas(),null);
			
		}
		if (tipoh.getPropsVar()!=null)   {
			tipodev= new Tipodevuelto(tipoh.getPropsVar().getT(),tipoh.getID(),0,tipoh.getPropsVar().getTam(),null,null,null,null,null,null,tipoh.getPropsVar());
		}
		return tipodev;	
	}


	public Operador Op0() throws Exception
	{
		Operador devolver;
		if (al.consultaTipo(TipoToken.t_menor))
		{
			al.reconoceToken(TipoToken.t_menor);
			devolver=new Operador("compara_menor",Tipo.literal_booleano);
		}
		else
		{
		if (al.consultaTipo(TipoToken.t_mayor))
		{
			al.reconoceToken(TipoToken.t_mayor);
			devolver=new Operador("compara_mayor",Tipo.literal_booleano);
		}
		else
		{
		if (al.consultaTipo(TipoToken.t_menorIgual))
		{
			al.reconoceToken(TipoToken.t_menorIgual);
			devolver=new Operador("compara_menorigual",Tipo.literal_booleano);
		}
		else
		{
		if (al.consultaTipo(TipoToken.t_mayorIgual))
		{
			al.reconoceToken(TipoToken.t_mayorIgual);
			devolver=new Operador("compara_mayorigual",Tipo.literal_booleano);
		}
		else
		{
		if (al.consultaTipo(TipoToken.t_igual))
		{
			al.reconoceToken(TipoToken.t_igual);
			devolver=new Operador("compara_igual",Tipo.literal_booleano);
		}
		else
		{
		if (al.consultaTipo(TipoToken.t_distinto))
		{
			al.reconoceToken(TipoToken.t_distinto);
			devolver=new Operador("compara_distinto",Tipo.literal_booleano);
		}
		else throw new Exception ("Error Sintactico contextual: Error de tipos"+ " Linea: "+ al.getLinea() + " Columna: "+ al.getColumna());  
		}
		}
		}
		}
		}
		return devolver;		
	}
	
	public Operador Op1() throws Exception
	{
		Operador devolver = null;
		if (al.consultaTipo(TipoToken.t_suma))
		{
			al.reconoceToken(TipoToken.t_suma);
			devolver=new Operador("suma",Tipo.literal_numerico);
		}
		else
		{
		if (al.consultaTipo(TipoToken.t_resta))
		{
			al.reconoceToken(TipoToken.t_resta);
			devolver=new Operador("resta",Tipo.literal_numerico);			
		}
		}
		return devolver;
	}
	
	public Operador Op2() throws Exception
	{
		Operador devolver = null;
		if (al.consultaTipo(TipoToken.t_mult))
		{
			al.reconoceToken(TipoToken.t_mult);
			devolver=new Operador("multiplica",Tipo.literal_numerico);
		}
		else
		{
		if (al.consultaTipo(TipoToken.t_div))
		{
			al.reconoceToken(TipoToken.t_div);
			devolver=new Operador("divide",Tipo.literal_numerico);
		}
		else{
		if (al.consultaTipo(TipoToken.t_mod))
		{
			al.reconoceToken(TipoToken.t_mod);
			devolver=new Operador("modulo",Tipo.literal_numerico);
		}
		}
		}
		return devolver;
	}
	
	public Operador Op3() throws Exception
	{
		Operador devolver;
		if (al.consultaTipo(TipoToken.t_dDer))
		{
			al.reconoceToken(TipoToken.t_dDer);
			devolver=new Operador("desplaza_derecha",Tipo.literal_natural);
		}
		else
		{
			al.reconoceToken(TipoToken.t_dIzq);
			devolver=new Operador("desplaza_izquierda",Tipo.literal_natural);
		}
		return devolver;
	}
	
	public Operador Op4a() throws Exception
	{
		Operador devolver;
		if (al.consultaTipo(TipoToken.t_no))
		{
			al.reconoceToken(TipoToken.t_no);
			devolver=new Operador("no_logico",Tipo.literal_booleano);
		}
		else{
			al.reconoceToken(TipoToken.t_menos);	
			devolver=new Operador("cambia_signo",Tipo.literal_numerico);
		}
		return devolver;
	}
	
	public Operador Op4na() throws Exception{
		Operador devolver = null;
		if(al.consultaTipo(TipoToken.t_cast)){
			Token t = al.reconoceToken(TipoToken.t_cast);
			if(t.getLexema().equals("(real)"))
			{	
				devolver=new Operador("convierte_real",Tipo.literal_real);
			}else{
			if(t.getLexema().equals("(ent)"))
			{
				devolver=new Operador("convierte_entero",Tipo.literal_entero);
			}else{
			if(t.getLexema().equals("(nat)"))
			{
				devolver=new Operador("convierte_natural",Tipo.literal_natural);
			}else{
			if(t.getLexema().equals("(car)"))
			{
				devolver=new Operador("convierte_caracterl",Tipo.literal_caracter);						}
			}
			}	
			}
		}
	return devolver;
	}	
	
	public boolean esBooleano(Tipo Tipo)
	{														
		Tipo bool=Tipo.literal_booleano;
		return bool.equals(Tipo);
	}
	
	public boolean esEntero(Tipo tipo) 
	{
		Tipo ent=Tipo.literal_entero;
		return ent.equals(tipo);
	}
	
	public boolean esNatural(Tipo tipo) 
	{
		Tipo nat=Tipo.literal_natural;
		return nat.equals(tipo);
	}
	
	public boolean esCaracter(Tipo Tipo) 
	{
		Tipo car=Tipo.literal_caracter;
		return car.equals(Tipo);
	}
	
	public boolean esReal(Tipo tipo) 
	{
		Tipo real=Tipo.literal_real;
		return real.equals(tipo);
	}
	
	public boolean esNumerico(Tipo tipo) {
		Tipo num=Tipo.literal_numerico;
		return num.equals(tipo);
	}

	public void crearFichCompilado(String compilado) 
	{
		PrintWriter f = null;
		try {
			if (cod.contains("stop")){
				f = new PrintWriter (new FileOutputStream(compilado,true));
				int i=0;
				while (i<cod.size()){
					f.println((i+1)+ " "+ cod.get(i));
					i++;
				}
				f.close();
			}
			else {
				File salida = new File(compilado);
				salida.delete();
			}
		} catch (FileNotFoundException e) {e.printStackTrace();}		
	}
	
	private void parchea(int etqaux, int etq2) {
		if(cod.get(etqaux).startsWith("ir-a")) cod.set(etqaux, "ir-a "+ (etq2+1));
		if(cod.get(etqaux).startsWith("ir-v")) cod.set(etqaux, "ir-v "+ (etq2+1));
		if(cod.get(etqaux).startsWith("ir-f")) cod.set(etqaux, "ir-f "+ (etq2+1));
		if(cod.get(etqaux).startsWith("ir-f")) cod.set(etqaux, "ir-f "+ (etq2+1));
		if(cod.get(etqaux).startsWith("apila")) cod.set(etqaux, "apila "+ (etq2+1));

	}	
	
	private int max(int n2, int nmax2) {
		if(n2>nmax2) return n2;
		else return nmax2;
	}
	
	private void inicio(int nmax, int dir) {
		emite ("apila "+ (nmax+2),0);
		emite ("desapila-dir 1",1);
		emite ("apila "+ (1+nmax+dir),2);
		emite ("desapila-dir 0",3);
	}

	private void prologo(int n2, int dir2) {
		emite("apila-dir 0");
		emite("apila 2");
		emite("suma");
		emite("apila-dir "+(1+n2));
		emite("desapila-ind");
		emite("apila-dir 0");
		emite("apila 3");
		emite("suma");
		emite("desapila-dir "+(1+n2));
		emite("apila-dir 0");
		emite("apila "+ (dir2+2));
		emite("suma"); 
		emite("desapila-dir 0");
	}
	
	private void epilogo(int n2) {
		emite("apila-dir "+(1+n2));
		emite("apila 2");
		emite("resta");
		emite("apila-ind");
		emite("apila-dir "+ (1+n2));
		emite("apila 3");
		emite("resta");
		emite("copia");
		emite("desapila-dir 0");
		emite("apila 2");
		emite("suma");
		emite("apila-ind");
		emite("desapila-dir "+(1+n2));
	}
	
	private int apila_ret() {
		emite("apila-dir 0");
		emite("apila 1");
		emite("suma");
		etq=etq+3;
		emite("apila ?");
		int etqaux=etq;
		emite("desapila-ind");
		etq=etq+2;
		return etqaux;
	}
	
	private void fin_paso() {
		emite("desapila");
	}

	private void inicio_paso() {
		emite("apila-dir 0");
		emite("apila 3");
		emite("suma");
	}
	
	private int longDireccionParForma1(Parametro parametros) {
		return 2;
	}
	
	private void direccionParFormal(Parametro parametros) {
		emite("apila " + parametros.getDirecc()); 
		emite("suma");
	}
	
	private boolean escampo(ArrayList<Campo> campos, String lexema) {
		Iterator<Campo> it= campos.iterator();
		Campo aux;
		while(it.hasNext()){
			aux=(Campo)it.next();
			if(aux.getId().contentEquals(lexema))
				return true;
		}	
		return false;
	}
	
	private int longAccesoVar(String lexema) throws Exception {
		if (ts.consultaTipo(lexema).equals(ClaseTabla.pvar))
			return 4;
		else return 3;
	}

	private void accesoVar(String lexema) throws Exception {
		emite("apila-dir "+ (1+ts.consultaNivel(lexema,n)));
		emite("apila " + (ts.consultaDir(lexema,n)));
		emite("suma");
		if (ts.consultaTipo(lexema).equals(ClaseTabla.pvar)){
			emite("apila-ind");
		}			
	}
	

	private Tipodevuelto referencia(Tipodevuelto tipo) throws Exception {		
		if(tipo.getTipo().equals(Tipo.ref)) {
			if(ts.existeID(tipo.getID())){
				Tipodevuelto tipo2= new Tipodevuelto(ts.consultaTipo(tipo.getPropsRef().getID()),tipo.getPropsRef().getID(),0,ts.consultaTamano(tipo.getPropsRef().getID()),ts.damePropsArray(tipo.getPropsRef().getID(),n),ts.damePropsPuntero(tipo.getPropsRef().getID(),n),ts.damePropsReg(tipo.getPropsRef().getID(),n),ts.damePropsRef(tipo.getPropsRef().getID(),n),ts.damePropsProc(tipo.getPropsRef().getID(),n),ts.damePropsTBas(tipo.getPropsRef().getID(),n),ts.damePropsVar(tipo.getPropsRef().getID(),n));
				return referencia(tipo2);
			}
			else throw new Exception ("Error en referencia");
		}
		else return tipo;		
	}//-->cuando sea referencia, creo un tipo devuelto con el tipo y el id,y llamo recursivamente
	
	private boolean compatibles(Parametro tipo1, Expresion e) throws Exception {
		if(tipo1.getPropsArray()!=null && e.gettipo().toString().equals("array")){
			Array a = null;
			if( (ts.damePropsArray(e.getId(),n)!=null ))
				a= ts.damePropsArray(e.getId(),n);
			else if(ts.damePropsArray(e.getId(),n)==null)
				a= ts.damePropsVar(e.getId(),n).getPropsArray();

			if(tipo1.getPropsArray().getNelems()== a.getNelems()){
				Tipodevuelto tipo= new Tipodevuelto(Tipo.array,"",tipo1.getPropsArray().getNelems(),tipo1.getPropsArray().getTam(),tipo1.getPropsArray(),null,null,null,null,null,null);
				Tipodevuelto tbase1=tipobase(tipo);
				Tipodevuelto tipo2= new Tipodevuelto(Tipo.array,e.getId(),a.getNelems(),a.getTam(),a,null,null,null,null,null,null);
				Tipodevuelto tbase2= tipobase(tipo2);
				tbase1=referencia(tbase1);
				tbase2=referencia(tbase2);
				Expresion ebase= new Expresion(tbase2.getID(),tbase2.getTipo(),null);
				return compatibles(tbase1,ebase);
			}
			else return false;

		}
			
		if(tipo1.getPropsReg()!=null && e.gettipo().toString().equals("registro")){
		        Registro r;
		        
				if (ts.damePropsReg(e.getId(),n)==null) r=ts.damePropsVar(e.getId(),n).getPropsReg();
				else r=ts.damePropsReg(e.getId(),n);
				if (tipo1.getPropsReg().getNum_campos()==r.getNum_campos()){
						boolean camposCompatibles=true;
						for(int i=0;i<r.getNum_campos();i++)
						{
							Campo c1= tipo1.getPropsReg().getCampos().get(i);
							Campo c2= r.getCampos().get(i);
							//compribar que cada campo tiene el mismo tipo
							Tipodevuelto tcampo1=tipoCampo(c1);
							Tipodevuelto tcampo2=tipoCampo(c2);
							tcampo1=referencia(tcampo1);
							tcampo2=referencia(tcampo2);
							Expresion ecampo2= new Expresion(tcampo2.getID(),tcampo2.getTipo(),null);
							camposCompatibles=compatibles(tcampo1,ecampo2);
							
						}
						return camposCompatibles;
				}
				else return false;
		}

		if(tipo1.getPropsPunt()!=null && e.gettipo().toString().equals("puntero")){

			Puntero p;
			if(e.getId().toString().equals("nulo")) return true;
			
			if(ts.damePropsPuntero(e.getId(),n)!=null) p= ts.damePropsPuntero(e.getId(),n);
			else p=ts.damePropsVar(e.getId(),n).getPropsPunt();
			Tipodevuelto tipo= new Tipodevuelto(Tipo.puntero,"",0,tipo1.getPropsPunt().getTam(),null,tipo1.getPropsPunt(),null,null,null,null,null);
			Tipodevuelto tbase1=tipobase(tipo);
			Tipodevuelto tipo2= new Tipodevuelto(Tipo.puntero,e.getId(),0,p.getTam(),null,p,null,null,null,null,null);
			Tipodevuelto tbase2= tipobase(tipo2);
			Expresion ebase= new Expresion(tbase2.getID(),tbase2.getTipo(),null);
			return compatibles(tbase1,ebase);
		}
		if(tipo1.getPropsTBas()!=null && e.gettipo().toString().equals("basico")){

				
			TipoBasico tb;
			if(e.getmodo().toString().equals("variable")) tb=ts.damePropsVar(e.getId(),n).getPropsTBas();
			else tb=ts.damePropsTBas(e.getId(),n);
			return compatibles(tb.getT(),tb.getT());

		}
		if(tipo1.getPropsRef()!=null || e.gettipo().toString().equals("ref")){
			//tachaaan que pasa aqui?
			//meto de aqui
			if(tipo1.getPropsRef()!=null){
				if( e.gettipo().toString().equals("ref")){
					return compatibles(tipo1.getPropsRef().getT(), ts.consultaTipo(e.getId()));
				}
				else{
					return compatibles(tipo1.getPropsRef().getT(), e.gettipo());
				}	
				
			}
		}//aqui
		else 	return compatibles(tipo1.getPropsVar().getT(),e.gettipo());//si no , son literales...
		
	return false;
		
	}
	
	private boolean compatibles(Tipodevuelto tipo1,Expresion e) throws Exception {
		//en mi opinion el visitados lo podemos poner o no, es simplemente para optimizar...
		
		if(tipo1.getTipo().toString().equals("array") && e.gettipo().toString().equals("array")){
			if(tipo1.getID().equals(e.getId())) return true;
			Array a = null;
			if( (ts.damePropsArray(e.getId(),n)!=null ))
				a= ts.damePropsArray(e.getId(),n);
			else if(ts.damePropsArray(e.getId(),n)==null)
				a= ts.damePropsVar(e.getId(),n).getPropsArray();

			if(tipo1.getPropsArray().getNelems()== a.getNelems()){
				Tipodevuelto tbase1=tipobase(tipo1);
				Tipodevuelto tipo2= new Tipodevuelto(Tipo.array,e.getId(),a.getNelems(),a.getTam(),a,null,null,null,null,null,null);
				Tipodevuelto tbase2= tipobase(tipo2);
				tbase1=referencia(tbase1);
				tbase2=referencia(tbase2);
				Expresion ebase= new Expresion(tbase2.getID(),tbase2.getTipo(),null);
				return compatibles(tbase1,ebase);
			}
			else return false;

		}
			
		if(tipo1.getTipo().toString().equals("registro") && e.gettipo().toString().equals("registro")){
		        Registro r;
		        if(tipo1.getID().equals(e.getId())) return true;
				if (ts.damePropsReg(e.getId(),n)==null) r=ts.damePropsVar(e.getId(),n).getPropsReg();
				else r=ts.damePropsReg(e.getId(),n);
				if (tipo1.getPropsReg().getNum_campos()==r.getNum_campos()){
						boolean camposCompatibles=true;
						for(int i=0;i<r.getNum_campos();i++)
						{
							Campo c1= tipo1.getPropsReg().getCampos().get(i);
							Campo c2= r.getCampos().get(i);
							//compribar que cada campo tiene el mismo tipo
							Tipodevuelto tcampo1=tipoCampo(c1);
							Tipodevuelto tcampo2=tipoCampo(c2);
							tcampo1=referencia(tcampo1);
							tcampo2=referencia(tcampo2);
							Expresion ecampo2= new Expresion(tcampo2.getID(),tcampo2.getTipo(),null);
							camposCompatibles=compatibles(tcampo1,ecampo2);
							
						}
						return camposCompatibles;
				}
				else return false;
		}

		if(tipo1.getTipo().toString().equals("puntero") && e.gettipo().toString().equals("puntero")){

			Puntero p;
			if(e.getId().toString().equals("nulo") || tipo1.getID().equals(e.getId()) ) return true;
			
			if(ts.damePropsPuntero(e.getId(),n)!=null) p= ts.damePropsPuntero(e.getId(),n);
			else p=ts.damePropsVar(e.getId(),n).getPropsPunt();
			Tipodevuelto tbase1=tipobase(tipo1);
			Tipodevuelto tipo2= new Tipodevuelto(Tipo.puntero,e.getId(),0,p.getTam(),null,p,null,null,null,null,null);
			Tipodevuelto tbase2= tipobase(tipo2);
			Expresion ebase= new Expresion(tbase2.getID(),tbase2.getTipo(),null);
			return compatibles(tbase1,ebase);
		}
		if(tipo1.getTipo().toString().equals("basico") && e.gettipo().toString().equals("basico")){

			if(tipo1.getID().equals(e.getId())) return true;	
			TipoBasico tb;
			if(e.getmodo().toString().equals("variable")) tb=ts.damePropsVar(e.getId(),n).getPropsTBas();
			else tb=ts.damePropsTBas(e.getId(),n);
			return compatibles(tb.getT(),tb.getT());

		}
		if(tipo1.getTipo().toString().equals("ref") || e.gettipo().toString().equals("ref")){
			//tachaaan que pasa aqui?
			}
		else return compatibles(tipo1.getTipo(),e.gettipo());//si no , son literales...
	return false;
	}
		
	
	private boolean compatibles(Tipo t1, Tipo t2){
	//Comparacion de literales	
		if(t1.equals(t2))
			return true;
		if((t1.equals(Tipo.literal_numerico)&&(t2.equals(Tipo.literal_entero) || t2.equals(Tipo.literal_natural) || t2.equals(Tipo.literal_real)))
			|| (t2.equals(Tipo.literal_numerico)&&(t1.equals(Tipo.literal_entero) || t1.equals(Tipo.literal_natural) || t1.equals(Tipo.literal_real)))
			|| (t1.equals(Tipo.literal_entero) && t2.equals(Tipo.literal_natural))
			|| (t1.equals(Tipo.literal_real) && (t2.equals(Tipo.literal_entero) || t2.equals(Tipo.literal_natural))))
			return true;	
		return false;
	}
	
	private void pasoParametro(Modo getmodo, Parametro parametros) {		
		if(parametros.getModo().equals(Modo.valor) && getmodo.equals(Modo.variable)){
			if(parametros.getPropsArray()!=null) emite("mueve "+ parametros.getPropsArray().getTam());
			if(parametros.getPropsPunt()!=null) emite("mueve "+ parametros.getPropsPunt().getTam());
			if(parametros.getPropsRef()!=null) emite("mueve "+ parametros.getPropsRef().getTam());
			if(parametros.getPropsReg()!=null) emite("mueve "+ parametros.getPropsReg().getTam());
			if(parametros.getPropsVar()!=null) emite("mueve "+ parametros.getPropsVar().getTam());
			if(parametros.getPropsTBas()!=null) emite("mueve "+ parametros.getPropsTBas().getTam());
		}
		else emite("desapila-ind");
	}
	
	private int longPasoParametro(Modo getmodo, Parametro parametros) {
		return 1;
	}	
}
